-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #214 from nathanKramer/add-desugaring-examples
Add desugaring examples
- Loading branch information
Showing
8 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/expect | ||
|
||
# uncomment line below for debugging | ||
# exp_internal 1 | ||
|
||
set timeout 7 | ||
|
||
spawn ./examples/DesugaringAwait/main | ||
|
||
expect "Hello Alice\r\n" | ||
expect "Hello Bob\r\n" | ||
expect "Hello Alice\r\n" | ||
expect "Hello Bob\r\n" | ||
|
||
expect "Type in something and press Enter:\r\n" | ||
send "hello\r\n" | ||
expect "Your input was: hello\r\n" | ||
expect "Type in something and press Enter:\r\n" | ||
send "yo\r\n" | ||
expect "Your input was: \r\nyo\r\n" { | ||
expect eof | ||
exit 0 | ||
} | ||
|
||
puts stderr "\nError: output was different from expected value." | ||
exit 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/usr/bin/expect | ||
|
||
# uncomment line below for debugging | ||
# exp_internal 1 | ||
|
||
set timeout 7 | ||
|
||
spawn ./examples/DesugaringTry/main | ||
|
||
expect -exact "(Ok {birthYear: 1990, name: \"Alice\"})\r\n(Ok {birthYear: 1990, name: \"Alice\"})\r\n" { | ||
expect eof | ||
exit 0 | ||
} | ||
|
||
puts stderr "\nError: output was different from expected value." | ||
exit 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Desugaring ! | ||
|
||
<details> | ||
<summary>What's syntax sugar?</summary> | ||
|
||
Syntax within a programming language that is designed to make things easier | ||
to read or express. It allows developers to write code in a more concise, readable, or | ||
convenient way without adding new functionality to the language itself. | ||
</details> | ||
|
||
Desugaring converts syntax sugar (like `x + 1`) into more fundamental operations (like `Num.add x 1`). | ||
|
||
Let's see how `!` is desugared, we'll start with a simple example: | ||
```roc | ||
file:main.roc:snippet:bang | ||
``` | ||
After desugaring, this becomes: | ||
```roc | ||
file:main.roc:snippet:await | ||
``` | ||
[Task.await](https://www.roc-lang.org/builtins/Task#await) takes the success value from a given | ||
Task and uses that to generate a new Task. | ||
It's type is `Task a b, (a -> Task c b) -> Task c b`. | ||
|
||
The type of `Stdout.line` is `Str -> Task {} [StdoutErr Err]`. | ||
Because `Stdout.line` does not return anything upon success, we use `\_` in the desugared version, | ||
there is nothing to pass to the next Task. | ||
|
||
You'll see that the version with `!` looks a lot simpler! | ||
|
||
Note that for the last line in the first snippet `Stdout.line "Hello Bob"`, you could have also written | ||
`Stdout.line! "Hello Bob"`. `!` is not necessary on the last line but we allow it for consistency and | ||
to prevent confusion for beginners. | ||
|
||
`!` also makes it easy to work with variables, let's take a look: | ||
```roc | ||
file:main.roc:snippet:bangInput | ||
``` | ||
|
||
This gets desugared to: | ||
```roc | ||
file:main.roc:snippet:awaitInput | ||
``` | ||
|
||
This is similar to before but now the `input = Stdin.line!` gets converted to `Task.await Stdin.line \input ->`. | ||
With `!` you can write code in a mostly familiar way while also getting the benefits of Roc's | ||
error handling and the seperation of pure and effectful code. | ||
|
||
Note: this desugaring is very similar to that of [`?`](https://www.roc-lang.org/examples/DesugaringTry/README.html). | ||
|
||
## Full Code | ||
```roc | ||
file:main.roc | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" } | ||
|
||
import pf.Stdin | ||
import pf.Stdout | ||
|
||
main = | ||
helloBang! | ||
helloAwait! | ||
readInputBang! | ||
readInputAwait! | ||
|
||
### start snippet bang | ||
helloBang = | ||
Stdout.line! "Hello Alice" | ||
Stdout.line "Hello Bob" | ||
### end snippet bang | ||
|
||
helloAwait = | ||
### start snippet await | ||
Task.await (Stdout.line "Hello Alice") \_ -> | ||
Stdout.line "Hello Bob" | ||
### end snippet await | ||
|
||
### start snippet bangInput | ||
readInputBang = | ||
Stdout.line! "Type in something and press Enter:" | ||
input = Stdin.line! | ||
Stdout.line! "Your input was: $(input)" | ||
### end snippet bangInput | ||
|
||
### start snippet awaitInput | ||
readInputAwait = | ||
Task.await (Stdout.line "Type in something and press Enter:") \_ -> | ||
Task.await Stdin.line \input -> | ||
Stdout.line "Your input was: $(input)" | ||
### end snippet awaitInput |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Desugaring ? | ||
|
||
<details> | ||
<summary>What's syntax sugar?</summary> | ||
|
||
Syntax within a programming language that is designed to make things easier | ||
to read or express. It allows developers to write code in a more concise, readable, or | ||
convenient way without adding new functionality to the language itself. | ||
</details> | ||
|
||
Desugaring converts syntax sugar (like `x + 1`) into more fundamental operations (like `Num.add x 1`). | ||
|
||
Let's see how `?` is desugared. In this example we will extract the name and birth year from a | ||
string like `"Alice was born in 1990"`. | ||
```roc | ||
file:main.roc:snippet:question | ||
``` | ||
|
||
After desugaring, this becomes: | ||
```roc | ||
file:main.roc:snippet:try | ||
``` | ||
|
||
[Result.try](https://www.roc-lang.org/builtins/Result#try) takes the success | ||
value from a given Result and uses that to generate a new Result. | ||
It's type is `Result a err, (a -> Result b err) -> Result b err`. | ||
|
||
`birthYear = Str.toU16? birthYearStr` is converted to `Str.toU16 birthYearStr |> Result.try \birthYear ->`. | ||
As you can see, the first version is a lot nicer! | ||
|
||
Thanks to `?`, you can write code in a mostly familiar way while also getting the benefits of Roc's | ||
error handling. | ||
|
||
Note: this desugaring is very similar to that of [`!`](https://www.roc-lang.org/examples/DesugaringAwait/README.html). | ||
|
||
## Full Code | ||
```roc | ||
file:main.roc | ||
``` | ||
|
||
## Output | ||
|
||
Run this from the directory that has `main.roc` in it: | ||
|
||
``` | ||
$ roc main.roc | ||
(Ok {birthYear: 1990, name: "Alice"}) | ||
(Ok {birthYear: 1990, name: "Alice"}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br" } | ||
|
||
import pf.Stdout | ||
|
||
main = | ||
Stdout.line! (Inspect.toStr (parseNameAndYear "Alice was born in 1990")) | ||
Stdout.line! (Inspect.toStr (parseNameAndYearTry "Alice was born in 1990")) | ||
|
||
### start snippet question | ||
parseNameAndYear : Str -> Result { name : Str, birthYear : U16 } _ | ||
parseNameAndYear = \str -> | ||
{ before: name, after: birthYearStr } = Str.splitFirst? str " was born in " | ||
birthYear = Str.toU16? birthYearStr | ||
Ok { name, birthYear } | ||
### end snippet question | ||
|
||
parseNameAndYearTry = \str -> | ||
### start snippet try | ||
str | ||
|> Str.splitFirst " was born in " | ||
|> Result.try \{ before: name, after: birthYearStr } -> | ||
Str.toU16 birthYearStr | ||
|> Result.try \birthYear -> | ||
Ok { name, birthYear } | ||
### end snippet try | ||
|
||
expect | ||
parseNameAndYear "Alice was born in 1990" == Ok { name: "Alice", birthYear: 1990 } | ||
|
||
expect | ||
parseNameAndYearTry "Alice was born in 1990" == Ok { name: "Alice", birthYear: 1990 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters