Open smores56 opened 1 week ago
Would love to have a go at this! Looking into it, will provide an update
I can give you some good pointers on this.
First step is to implement a new variant in crates/compiler/parse/src/ast.rs
, probably something like ResultTryQuestion
or something, that is almost identical to TaskAwaitBang(&'a Expr<'a>).
You should add some snapshot tests in crates/compiler/test_syntax/tests/snapshots/pass
and confirm it parses correctly.
That is probably one PR.
Then the next step is to desugar it, which I've nicknamed "unwrap" because the best place I think to do this is directly after all the Expr's get desugared but before the rest of canonicalisation. Specifically, in crates/compiler/can/src/suffixed.rs
, you will find the unwrap_suffixed_expression which is responsible for desugaring the !
operator. So we can modify this to also handle the ?
suffix. You can find the tests for this in crates/compiler/can/tests/test_suffixed.rs
If you need any assistance with parsing @joshuawarner32 is definitely the expert. For more general things @kdziamura and myself have been working in this part of the compiler recently. Hope this helps. 😍
Thanks @lukewilliamboswell!
Issue following from discussion in Zulip chat.
We want to add Rust's try operator, the
?
, to Roc, making early returns onErr
cleaner. This will work just like!
works when it desugars toTask.await
.There are many benefits to having
?
added to Roc, including "flatter" code, better readability, and better concision, but these could also be achieved if ! was extended to work forResult
s or even anything implementing a hypotheticalAndThen
ability. However, the mental overhead of understanding that a return type'sAndThen
implementation is being leveraged, as well as the teach-ability damage to the language, make generalizing the ! operator cost-prohibitive. By having!
just forTask
s and?
just forResult
s, we get the cleanliness benefits of each operator without making the language much harder to learn, and we prevent potential exploitation of a generalized!
operator.This also paves the way for the eventual deprecation and removal of backpassing from the language.
Some things we should consider when implementing this operator:
!
operator, but will instead translate toResult.try
every time?
is used on isn't a tag union, but also if there are extra or missing variants from[Ok _, Err _]