Skip to content

Commit

Permalink
Merge pull request #214 from nathanKramer/add-desugaring-examples
Browse files Browse the repository at this point in the history
Add desugaring examples
  • Loading branch information
Anton-4 authored Oct 7, 2024
2 parents 423d54d + cd20ab1 commit 8e21e3f
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 0 deletions.
7 changes: 7 additions & 0 deletions ci_scripts/all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ expect ci_scripts/expect_scripts/CommandLineArgs.exp
$ROC build ./examples/CommandLineArgsFile/main.roc
expect ci_scripts/expect_scripts/CommandLineArgsFile.exp

$ROC build ./examples/DesugaringAwait/main.roc
expect ci_scripts/expect_scripts/DesugaringAwait.exp

$ROC build ./examples/DesugaringTry/main.roc
$ROC test ./examples/DesugaringTry/main.roc
expect ci_scripts/expect_scripts/DesugaringTry.exp

$ROC build ./examples/Tuples/main.roc
expect ci_scripts/expect_scripts/Tuples.exp

Expand Down
26 changes: 26 additions & 0 deletions ci_scripts/expect_scripts/DesugaringAwait.exp
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
16 changes: 16 additions & 0 deletions ci_scripts/expect_scripts/DesugaringTry.exp
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
54 changes: 54 additions & 0 deletions examples/DesugaringAwait/README.md
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
```
36 changes: 36 additions & 0 deletions examples/DesugaringAwait/main.roc
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
49 changes: 49 additions & 0 deletions examples/DesugaringTry/README.md
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"})
```
31 changes: 31 additions & 0 deletions examples/DesugaringTry/main.roc
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 }
2 changes: 2 additions & 0 deletions examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ You can find the source code for all of these at [github.com/roc-lang/examples](
- [Looping Tasks](/TaskLoop/README.html)
- [Record Builder](/RecordBuilder/README.html)
- [Encoding & Decoding Abilities](/EncodeDecode/README.html)
- [Desugaring !](/DesugaringAwait/README.html)
- [Desugaring ?](/DesugaringTry/README.html)
- [Custom Inspect](/CustomInspect/README.html)
- [Least Squares](/LeastSquares/README.html)
- [Towers of Hanoi](/TowersOfHanoi/README.html)
Expand Down

0 comments on commit 8e21e3f

Please sign in to comment.