Skip to content

Commit

Permalink
Merge pull request #142 from exercism/unison-upgrade
Browse files Browse the repository at this point in the history
The Unison upgrade
  • Loading branch information
SimaDovakin authored Oct 7, 2024
2 parents a74cc45 + 4e7849f commit 86d9303
Show file tree
Hide file tree
Showing 174 changed files with 2,776 additions and 2,662 deletions.
2 changes: 1 addition & 1 deletion docs/INSTALLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Installation Options

The current Unison release is available for Mac OS X, 64-bit Linux, and Windows users! We hope that if you are trying out Unison you'll come talk to us in the Exercism forum or in the [Unison language slack](http://unison-lang.org/slack). Come ask questions, and report issues you might encounter! We want you to have a welcoming and positive experience when getting started! 😊
The current Unison release is available for Mac OS X, 64-bit Linux, and Windows users! We hope that if you are trying out Unison you'll come talk to us in the Exercism forum or in the [Unison Discord](https://unison-lang.org/discord). Come ask questions, and report issues you might encounter! We want you to have a welcoming and positive experience when getting started! 😊

Unison can be downloaded with [homebrew](https://brew.sh/), [Nix](https://github.com/ceedubs/unison-nix/#usage), or directly via packaged binaries. All of these download options are described in the [Installation instructions page of our website](https://www.unison-lang.org/learn/quickstart/#installation-options). Once you have the UCM installed, head back here!

Expand Down
2 changes: 1 addition & 1 deletion docs/LEARNING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ For reference material, the [Unison language reference](https://www.unison-lang.

You may want to familiarize yourself with [Unison Share](https://share.unison-lang.org/), Unison's repository for public libraries and projects. The documentation for the standard library, [`base`](https://share.unison-lang.org/@unison/code/latest/namespaces/public/base/latest), contains helpful usage information.

👋 If you're ever stuck, we're happy to help. The #beginner-friendly channel in [the official Unison slack](http://unison-lang.org/slack) is filled with friendly people.
👋 If you're ever stuck, we're happy to help. The #beginner-friendly channel in [the official Unison Discord server](https://unison-lang.org/discord) is filled with friendly people.
6 changes: 3 additions & 3 deletions docs/RESOURCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

* [The Unison language documentation](https://www.unison-lang.org/learn/fundamentals/values-and-functions/terms/) is a great place to learn core Unison concepts
* [Unison Share](https://share.unison-lang.org/) is the repository where we host public libraries and code
* You can always ask questions in [the Unison slack](http://unison-lang.org/slack)
* You can always ask questions in [the Unison Discord](https://unison-lang.org/discord)
* [The Unison Blog](https://www.unison-lang.org/blog/) contains language updates and special topics
* An article about using [Unison's Remote ability to implement a Spark-like library](https://www.unison-lang.org/articles/distributed-datasets/)

## Videos

* [YOW! Lambda Jam 2021](https://www.youtube.com/watch?v=DF6zt0Q-pz4), by Rúnar Bjarnason
* [YOW! Lambda Jam 2021 - Part 1](https://www.youtube.com/watch?v=Adu75GJ0w1o), and [Part 2](https://www.youtube.com/watch?v=gy44CTCce0o), by Rúnar Bjarnason
* [Scale By the Bay 2019](https://www.youtube.com/watch?v=IvENPX0MAZ4), by Paul Chiusano
* This is a 32 minute talk that briefly covers the core ideas of Unison and talks about Unison's approach to refactoring.
* [Strange Loop 2019](https://www.youtube.com/watch?v=gCWtkvDQ2ZI), by Paul Chiusano
* This is a longer (40 min) introduction to the core ideas of Unison and probably the best talk to start with.
* [Scale By the Bay 2018](https://www.youtube.com/watch?v=v7L-5AQQkbM), by Paul Chiusano.
* [Lambda World 2018](https://www.youtube.com/watch?v=rp_Eild1aq8), by Rúnar Bjarnason also presented at [Øredev 2018](https://vimeo.com/311512465).
* [Scala World 2017](https://www.youtube.com/watch?v=knqlWboqf_U), by Paul Chiusano.
* [Full Stack Fest](https://www.youtube.com/watch?v=f6yA3t0dO-k) 2016, by Paul Chiusano
* [Full Stack Fest](https://www.youtube.com/watch?v=f6yA3t0dO-k) 2016, by Paul Chiusano
22 changes: 11 additions & 11 deletions docs/TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Writing Unison code is as simple as opening your terminal of choice and running the `ucm` command in the directory where you'll be writing your Unison code. Then you can use your favorite text editor to create or open a file with a `.u` suffix, like `scratch.u` or `hello.u`. The bulk of your workflow will be navigating between the running `ucm` command line instance and your `.u` file. The UCM automatically listens to changes in your `.u` suffixed file upon saving the file.

In lieu of a directory structure, Unison codebases are organized via "namespaces". You'll be exploring the standard library's namespace, called `base`, for useful functions and data types, and you'll be creating your own as you write Unison code. In the UCM, navigation in the codebase is done with the [`ls`](https://www.unison-lang.org/learn/ucm-commands/#ls), [`cd`](https://www.unison-lang.org/learn/ucm-commands/#cd), and [`view`](https://www.unison-lang.org/learn/ucm-commands/#view) commands—they're used for listing namespace content, moving throughout the namespace tree, and viewing source code, respectively.
In lieu of a directory structure, Unison codebases are organized via "namespaces". You'll be exploring the standard library's namespace, called `base`, for useful functions and data types, and you'll be creating your own as you write Unison code. In the UCM, navigation in the codebase is done with the [`ls`](https://www.unison-lang.org/learn/ucm-commands/#ls) and [`view`](https://www.unison-lang.org/learn/ucm-commands/#view) commands—they're used for listing namespace content and viewing source code, respectively.

While you can navigate and view your codebase via the UCM CLI, you may also want to see a nice graphical representation of your work. You can do that by issuing the [`ui`](https://www.unison-lang.org/learn/ucm-commands/#ui) command in the UCM CLI. It will open a browser window with a view of the code in your codebase. The local codebase UI is also a great way to explore functions in our standard library, called `base`, which might be useful in accomplishing the exercises. [Read more about the local codebase UI here](https://www.unison-lang.org/learn/tooling/local-codebase-u-i/).

Expand All @@ -18,21 +18,22 @@

### Quick overview

1. With the UCM watching the exercise directory, make your changes in the `<myFileName>.u` file
2. Save the `<myFileName>.u` file
3. If the file typechecks, run the `add` or `update` UCM commands
1. Create a new project using command [`project.create`](https://www.unison-lang.org/docs/tour/#part-2-tour) and provide the name for it (e.g. `project.create hello-world`)
2. With the UCM watching the exercise directory, make your changes in the `<myFileName>.u` file
3. Save the `<myFileName>.u` file
4. If the file typechecks, run the `add` or `update` UCM commands

* If the file does not typecheck, make changes to the code in your `<myFileName>.u` file until it compiles
4. Run the `load <myFileName>.test.u` command in the UCM cli to bring the tests into scope and run them
5. Run the `load <myFileName>.test.u` command in the UCM cli to bring the tests into scope and run them

### Detailed walk through

If you're working on an Exercism problem on the command line, most likely you'll be implementing your solution in the directory named after the given exercise. For example, if the exercise is `hello-world`, you should open the `ucm` from the command line after having `cd`'ed into `~/exercism/unison/hello-world`. Make your implementation changes in the `hello.u` file, and when you're satisfied with your implementation, enter the `add` or `update` command in the Unison codebase manager CLI (UCM) to add your work from the file into the codebase.
If you're working on an Exercism problem on the command line, most likely you'll be implementing your solution in the directory named after the given exercise. For example, if the exercise is `hello-world`, you should open the `ucm` from the command line after having `cd`'ed into `~/exercism/unison/hello-world` and create a project in the `ucm` (e.g. `project.create hello-world`). Make your implementation changes in the `hello.u` file, and when you're satisfied with your implementation, enter the `add` or `update` command in the Unison codebase manager CLI (UCM) to add your work from the file into the codebase.

The file that contains the tests for each exercise is suffixed `.test.u`. You'll want to use the `load` command in the UCM to bring the tests into scope and run them. The `load` command takes a file path as its argument. Here's what that might look like for the hello world exercise:
The file that contains the tests for each exercise is suffixed `.test.u`. You'll want to use the `load` command in the UCM to bring the tests into scope and run them. The `load` command takes a file path as its argument. Here's what that might look like for the hello world exercise and `hello-world` project:

```
.> load hello.test.u
hello-world/main> load hello.test.u
```

You should see a message from the UCM about the terms that were brought into scope and, importantly, the result of running the test:
Expand Down Expand Up @@ -63,7 +64,7 @@
hello : Text
.> update
hello-world/main> update
⍟ I've updated these names to your new definition:
Expand All @@ -73,7 +74,7 @@
Next we can re-load our tests to see if anything changed!

```
.> load hello.test.u
hello-world/main> load hello.test.u
Now evaluating any watch expressions (lines starting with `>`)... Ctrl+C cancels.
Expand All @@ -91,7 +92,6 @@
* If the old definition has any dependents, update will automatically propagate the change if possible, or create a [`todo`](https://www.unison-lang.org/learn/usage-topics/workflow-how-tos/resolve-conflicts/) item for future refactoring.
* [`load`](https://www.unison-lang.org/learn/ucm-commands/#load): Parses, typechecks and evaluates the given `.u` suffixed scratch file. Once typechecked and evaluated, you can add the terms to your codebase.
* [`ls`](https://www.unison-lang.org/learn/ucm-commands/#ls): Lists the contents of a namespace
* [`cd`](https://www.unison-lang.org/learn/ucm-commands/#cd): Navigates into the given namespace, creating the namespace if it does not exist
* [`view`](https://www.unison-lang.org/learn/ucm-commands/#view): View the source code of a given Unison definition
* [`ui`](https://www.unison-lang.org/learn/ucm-commands/#ui): Opens the local codebase UI
* `exit`: Closes the UCM
4 changes: 4 additions & 0 deletions docs/WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ The UCM will show the results of evaluating the expression upon saving the file.

For a more in-depth Exercism workflow, here's a [walk-through video][walk-through-vid] of implementing and testing an Exercism problem.

```exercism/caution
The walk-through video shows workflow for the older version of Unison. See new workflow [here](https://exercism.org/docs/tracks/unison/tests) with new project workflow.
```

## Codebase organization

A Unison codebase is organized by "namespaces." Namespaces function a bit like directories in a file system, except instead of containing files, they contain your Unison types and functions. Namespace paths are separated by dots, `.`. For example, we can refer to the `Text` namespace in the `base` namespace with `base.Text`.
Expand Down
8 changes: 4 additions & 4 deletions exercises/concept/lasagna/.meta/testAnnotation.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[
{
"name": "lasagna.test.ex1",
"test_code": "lasagna.test.ex1 = test.expect (expectedMinutesInOven === 40)"
"test_code": "let\n Test.expect (expectedMinutesInOven === 40)"
},
{
"name": "lasagna.test.ex2",
"test_code": "lasagna.test.ex2 = test.expect (preparationTimeInMinutes 5 === 10)"
"test_code": "let\n Test.expect (preparationTimeInMinutes 5 === 10)"
},
{
"name": "lasagna.test.ex3",
"test_code": "lasagna.test.ex3 = test.expect (elapsedTimeInMinutes 3 20 === 26)"
"test_code": "let\n Test.expect (elapsedTimeInMinutes 3 20 === 26)"
}
]
]
10 changes: 5 additions & 5 deletions exercises/concept/lasagna/.meta/testLoader.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Testing transcript

```ucm
.> load ./lasagna.u
.> add
.> load ./lasagna.test.u
.> add
.> move.term lasagna.tests tests
scratch/main> load ./lasagna.u
scratch/main> add
scratch/main> load ./lasagna.test.u
scratch/main> add
scratch/main> move.term lasagna.tests tests
```
50 changes: 25 additions & 25 deletions exercises/concept/pacman-rules/.meta/testAnnotation.json
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
[
{
"name": "pacmanRules.test.ex1",
"test_code": "pacmanRules.test.ex1 = let\n\tTest.label \"eatGhost, ghost gets eaten\" <| expect (eatGhost true true)"
"name": "eatGhost, ghost gets eaten",
"test_code": "let\n Test.label.deprecated \"eatGhost, ghost gets eaten\" <| expect (eatGhost true true)"
},
{
"name": "pacmanRules.test.ex2",
"test_code": "pacmanRules.test.ex2 = let\n\tTest.label \"eatGhost, ghost does not get eaten because no power pellet active\" <| expect (eatGhost false true === false)"
"name": "eatGhost, ghost does not get eaten because no power pellet active",
"test_code": "let\n Test.label.deprecated \"eatGhost, ghost does not get eaten because no power pellet active\" <| expect (eatGhost false true === false)"
},
{
"name": "pacmanRules.test.ex3",
"test_code": "pacmanRules.test.ex3 = let\n\tTest.label \"eatGhost, ghost does not get eaten because not touching ghost\" <| expect (eatGhost true false === false)"
"name": "eatGhost, ghost does not get eaten because not touching ghost",
"test_code": "let\n Test.label.deprecated \"eatGhost, ghost does not get eaten because not touching ghost\" <| expect (eatGhost true false === false)"
},
{
"name": "pacmanRules.test.ex4",
"test_code": "pacmanRules.test.ex4 = let\n\tTest.label \"score, score when eating dot\" <| expect (score false true)"
"name": "score, score when eating dot",
"test_code": "let\n Test.label.deprecated \"score, score when eating dot\" <| expect (score false true)"
},
{
"name": "pacmanRules.test.ex5",
"test_code": "pacmanRules.test.ex5 = let\n\tTest.label \"score, score when eating power pellet\" <| expect (score true false)"
"name": "score, score when eating power pellet",
"test_code": "let\n Test.label.deprecated \"score, score when eating power pellet\" <| expect (score true false)"
},
{
"name": "pacmanRules.test.ex6",
"test_code": "pacmanRules.test.ex6 = let\n\tTest.label \"score, no score when nothing eaten\" <| expect (score false false === false )"
"name": "score, no score when nothing eaten",
"test_code": "let\n Test.label.deprecated \"score, no score when nothing eaten\" <| expect (score false false === false )"
},
{
"name": "pacmanRules.test.ex7",
"test_code": "pacmanRules.test.ex7 = let\n\tTest.label \"lose if touching a ghost without a power pellet active\" <| expect (lose false true)"
"name": "lose if touching a ghost without a power pellet active",
"test_code": "let\n Test.label.deprecated \"lose if touching a ghost without a power pellet active\" <| expect (lose false true)"
},
{
"name": "pacmanRules.test.ex8",
"test_code": "pacmanRules.test.ex8 = let\n\tTest.label \"don't lose if touching a ghost with a power pellet active\" <| expect (lose true true === false)"
"name": "don't lose if touching a ghost with a power pellet active",
"test_code": "let\n Test.label.deprecated \"don't lose if touching a ghost with a power pellet active\" <| expect (lose true true === false)"
},
{
"name": "pacmanRules.test.ex9",
"test_code": "pacmanRules.test.ex9 = let\n\tTest.label \"don't lose if not touching a ghost\" <| expect (lose true false === false)"
"name": "don't lose if not touching a ghost",
"test_code": "let\n Test.label.deprecated \"don't lose if not touching a ghost\" <| expect (lose true false === false)"
},
{
"name": "pacmanRules.test.ex10",
"test_code": "pacmanRules.test.ex10 = let\n\tTest.label \"win if all dots eaten\" <| expect (win true false false)"
"name": "win if all dots eaten",
"test_code": "let\n Test.label.deprecated \"win if all dots eaten\" <| expect (win true false false)"
},
{
"name": "pacmanRules.test.ex11",
"test_code": "pacmanRules.test.ex11 = let\n\tTest.label \"don't win if all dots eaten, but touching a ghost\" <| expect (win true false true === false)"
"name": "don't win if all dots eaten, but touching a ghost",
"test_code": "let\n Test.label.deprecated \"don't win if all dots eaten, but touching a ghost\" <| expect (win true false true === false)"
},
{
"name": "pacmanRules.test.ex12",
"test_code": "pacmanRules.test.ex12 = let\n\tTest.label \"win if all dots eaten and touching a ghost with a power pellet active\" ,| expect (win true true true)"
"name": "win if all dots eaten and touching a ghost with a power pellet active",
"test_code": "let\n Test.label.deprecated \"win if all dots eaten and touching a ghost with a power pellet active\" <| expect (win true true true)"
}
]
]
10 changes: 5 additions & 5 deletions exercises/concept/pacman-rules/.meta/testLoader.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Testing transcript

```ucm
.> load ./pacmanRules.u
.> add
.> load ./pacmanRules.test.u
.> add
.> move.term pacmanRules.tests tests
scratch/main> load ./pacmanRules.u
scratch/main> add
scratch/main> load ./pacmanRules.test.u
scratch/main> add
scratch/main> move.term pacmanRules.tests tests
```
24 changes: 12 additions & 12 deletions exercises/concept/pacman-rules/pacmanRules.test.u
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
pacmanRules.test.ex1 = let
Test.label "eatGhost, ghost gets eaten" <| expect (eatGhost true true)
Test.label.deprecated "eatGhost, ghost gets eaten" <| expect (eatGhost true true)

pacmanRules.test.ex2 = let
Test.label "eatGhost, ghost does not get eaten because no power pellet active" <| expect (eatGhost false true === false)
Test.label.deprecated "eatGhost, ghost does not get eaten because no power pellet active" <| expect (eatGhost false true === false)

pacmanRules.test.ex3 = let
Test.label "eatGhost, ghost does not get eaten because not touching ghost" <| expect (eatGhost true false === false)
Test.label.deprecated "eatGhost, ghost does not get eaten because not touching ghost" <| expect (eatGhost true false === false)

pacmanRules.test.ex4 = let
Test.label "score, score when eating dot" <| expect (score false true)
Test.label.deprecated "score, score when eating dot" <| expect (score false true)

pacmanRules.test.ex5 = let
Test.label "score, score when eating power pellet" <| expect (score true false)
Test.label.deprecated "score, score when eating power pellet" <| expect (score true false)

pacmanRules.test.ex6 = let
Test.label "score, no score when nothing eaten" <| expect (score false false === false )
Test.label.deprecated "score, no score when nothing eaten" <| expect (score false false === false )

pacmanRules.test.ex7 = let
Test.label "lose if touching a ghost without a power pellet active" <| expect (lose false true)
Test.label.deprecated "lose if touching a ghost without a power pellet active" <| expect (lose false true)

pacmanRules.test.ex8 = let
Test.label "don't lose if touching a ghost with a power pellet active" <| expect (lose true true === false)
Test.label.deprecated "don't lose if touching a ghost with a power pellet active" <| expect (lose true true === false)

pacmanRules.test.ex9 = let
Test.label "don't lose if not touching a ghost" <| expect (lose true false === false)
Test.label.deprecated "don't lose if not touching a ghost" <| expect (lose true false === false)

pacmanRules.test.ex10 = let
Test.label "win if all dots eaten" <| expect (win true false false)
Test.label.deprecated "win if all dots eaten" <| expect (win true false false)

pacmanRules.test.ex11 = let
Test.label "don't win if all dots eaten, but touching a ghost" <| expect (win true false true === false)
Test.label.deprecated "don't win if all dots eaten, but touching a ghost" <| expect (win true false true === false)

pacmanRules.test.ex12 = let
Test.label "win if all dots eaten and touching a ghost with a power pellet active" <| expect (win true true true)
Test.label.deprecated "win if all dots eaten and touching a ghost with a power pellet active" <| expect (win true true true)

test> pacmanRules.tests = runAll [
pacmanRules.test.ex1,
Expand Down
Loading

0 comments on commit 86d9303

Please sign in to comment.