Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci_scripts/all_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fi

# opt-in list of examples to test (add examples as they are updated for the new compiler)
optin=(
"TryOperatorDesugaring"
"Tuples"
)

Expand Down Expand Up @@ -96,7 +97,6 @@ if is_optin "CommandLineArgsFile"; then
fi

if is_optin "TryOperatorDesugaring"; then
$ROC build ./examples/TryOperatorDesugaring/main.roc
$ROC test ./examples/TryOperatorDesugaring/main.roc
expect ci_scripts/expect_scripts/TryOperatorDesugaring.exp
fi
Expand Down
1 change: 1 addition & 0 deletions ci_scripts/check_format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ fi

# opt-in list of files to format check (add files as they are updated for the new compiler)
optin=(
"examples/TryOperatorDesugaring/main.roc"
"examples/Tuples/main.roc"
)

Expand Down
4 changes: 2 additions & 2 deletions ci_scripts/expect_scripts/TryOperatorDesugaring.exp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ set timeout 7

source ./ci_scripts/expect_scripts/shared-code.exp

spawn ./examples/TryOperatorDesugaring/main
spawn $env(ROC) ./examples/TryOperatorDesugaring/main.roc --no-cache

expect -exact "(Ok {birth_year: 1990, name: \"Alice\"})\r\n(Ok {birth_year: 1990, name: \"Alice\"})\r\n" {
expect -exact "Bob is older than Alice\r\n" {
expect eof {
check_exit_and_segfault
}
Expand Down
20 changes: 13 additions & 7 deletions examples/TryOperatorDesugaring/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,39 @@
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)`).
Desugaring converts syntax sugar (like `x + 1`) into more fundamental operations (like `x.plus(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:desugared
```

So `birth_year = Str.to_u16(birth_year_str)?` is converted to
So `birth_year = U16.from_str(birth_year_str)?` is converted to

```roc
when Str.to_u16(birth_year_str) is
Err(err2) -> return Err(err2)
Ok(birth_year) -> birth_year
birth_year = match U16.from_str(birth_year_str) {
Err(err) => {
return Err(err)
}
Ok(value) => value
}
```

As you can see, the first version is a lot nicer!

Thanks to `?`, you can write code in a familiar way and you get the benefits of Roc's
error handling to drastically reduce the likelihood of crashes.

## Full Code

```roc
file:main.roc
```
Expand All @@ -44,6 +51,5 @@ Run this from the directory that has `main.roc` in it:

```
$ roc main.roc
Ok({birth_year: 1990, name: "Alice"})
Ok({birth_year: 1990, name: "Alice"})
Bob is older than Alice
```
79 changes: 54 additions & 25 deletions examples/TryOperatorDesugaring/main.roc
Original file line number Diff line number Diff line change
@@ -1,36 +1,65 @@
app [main!] { cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.20.0/X73hGh05nNTkDHU06FHC0YfFaQB1pimX7gncRcao5mU.tar.br" }
main! : List(Str) => Try({}, _)
main! = |_args| {
person1 = parse_name_and_year("Alice was born in 1990")?
person2 = parse_name_and_year_try("Bob was born in 1985")?

import cli.Stdout
import cli.Arg exposing [Arg]
msg = if person1.birth_year < person2.birth_year {
"${person1.name} is older than ${person2.name}"
} else {
"${person2.name} is older than ${person1.name}"
}

main! : List Arg => Result {} _
main! = |_args|
Stdout.line!(Inspect.to_str(parse_name_and_year("Alice was born in 1990")))?
Stdout.line!(Inspect.to_str(parse_name_and_year_try("Alice was born in 1990")))?
echo!(msg)

Ok({})
Ok({})
}

### start snippet question
parse_name_and_year : Str -> Result { name : Str, birth_year : U16 } _
parse_name_and_year = |str|
{ before: name, after: birth_year_str } = Str.split_first(str, " was born in ")?
birth_year = Str.to_u16(birth_year_str)?
Ok({ name, birth_year })
parse_name_and_year : Str -> Try({ name : Str, birth_year : U16 }, _)
parse_name_and_year = |str| {
words = str.split_on(" ")

name = words.first()?

birth_year_str = List.last(words)?
# TODO: commented out line causes this panic:
# Interpreter error: error.InvalidMethodReceiver
# Execution error: error.InterpreterFailed
# birth_year_str = words.last()?
#
birth_year = U16.from_str(birth_year_str)?

Ok({ name, birth_year })
}
### end snippet question

### start snippet desugared
parse_name_and_year_try = |str|
when Str.split_first(str, " was born in ") is
Err(err1) ->
return Err(err1)

Ok({ before: name, after: birth_year_str }) ->
when Str.to_u16(birth_year_str) is
Err(err2) ->
return Err(err2)

Ok(birth_year) ->
Ok({ name, birth_year })
parse_name_and_year_try = |str| {
words = str.split_on(" ")
name = match words.first() {
Err(err) => {
return Err(err)
}
Ok(value) => value
}

# TODO: same as above
birth_year_str = match List.last(words) {
Err(err) => {
return Err(err)
}
Ok(value) => value
}

birth_year = match U16.from_str(birth_year_str) {
Err(err) => {
return Err(err)
}
Ok(value) => value
}

Ok({ name, birth_year })
}
### end snippet desugared

expect parse_name_and_year("Alice was born in 1990") == Ok({ name: "Alice", birth_year: 1990 })
Expand Down
Loading