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, we'll start with a simple example:
helloBang = Stdout.line! "Hello Alice" Stdout.line "Hello Bob"
After desugaring, this becomes:
Task.await (Stdout.line "Hello Alice") \_ -> Stdout.line "Hello Bob"
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:
readInputBang = Stdout.line! "Type in something and press Enter:" input = Stdin.line! Stdout.line! "Your input was: $(input)"
This gets desugared to:
readInputAwait = Task.await (Stdout.line "Type in something and press Enter:") \_ -> Task.await Stdin.line \input -> Stdout.line "Your input was: $(input)"
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 ?
.
Full Code
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.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