roc-lang / roc

A fast, friendly, functional language.
https://roc-lang.org
Universal Permissive License v1.0
3.86k stars 284 forks source link

Add syntax sugar that translates ? to Result.try #6828

Open smores56 opened 1 week ago

smores56 commented 1 week ago

Issue following from discussion in Zulip chat.

We want to add Rust's try operator, the ?, to Roc, making early returns on Err cleaner. This will work just like ! works when it desugars to Task.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 for Results or even anything implementing a hypothetical AndThen ability. However, the mental overhead of understanding that a return type's AndThen implementation is being leveraged, as well as the teach-ability damage to the language, make generalizing the ! operator cost-prohibitive. By having ! just for Tasks and ? just for Results, 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:

sekerez commented 6 days ago

Would love to have a go at this! Looking into it, will provide an update

lukewilliamboswell commented 6 days ago

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. 😍

sekerez commented 5 days ago

Thanks @lukewilliamboswell!