Desugaring ?
What's syntax sugar?
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.
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"
.
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 }
After desugaring, this becomes:
str |> Str.splitFirst " was born in " |> Result.try \{ before: name, after: birthYearStr } -> Str.toU16 birthYearStr |> Result.try \birthYear -> Ok { name, birthYear }
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 !
.
Full Code
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.16.0/O00IPk-Krg_diNS2dVWlI0ZQP794Vctxzv0ha96mK0E.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 }
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"})