This is unsatisfying for a couple of reasons: the match args (and frequently the match arm params) are a stutter of the function args, and the inner expr adds height and an extra scope that contributes to rightward drift.
Would people be open to an alternate syntax for this pattern that eliminated these two issues? Something like:
This is pretty nice in a lot of cases, especially when implementing common functional idioms. As a data point, basically every single function in https://github.com/reem/adamantium is just a single match block and rightward drift and associated extra code makes it much harder to look at then the equivalent Haskell.
However, this could be implemented in a 100% backwards compatible way, so is unlikely to be implemented pre-1.0.
I agree that this is a common pattern that would benefit from a bit of syntactic sugar. If this gets implemented I think it would be interesting to have something like GHC’s LambdaCase extension in Rust closures too:
Haskell syntax example:
let getJust = \case
Just x -> x
Nothing -> error "getJust: Nothing"
Rust:
let get_just = match {
Some(x) => x
None => fail!("get_just: None")
};
You can’t quite do it exactly with a Macro-By-Example (because you can’t gensym the generated function’s argument names, or at least I don’t know how), but this would be a pretty simple compiler plugin.
A rough sketch of how it might look but as an MBE (playpen link):
Was a typo, here’s a fix: playpen. But I agree, a proper syntax extension would be better. Errors and warnings wouldn’t be polluted with macro expansion locations; you could have an easy optional return value; you can have type parameters (haven’t even tried that one yet).
But it’s nice how much is prototypable with just macro_rules.
I can understand if people don’t want to add this, but it’s certainly a valid and useful use case. Its the core way you define functions in Haskell, and there’s a ton of existing Rust code that uses the more verbose form this sugars.
I thought of that syntax but don’t really like it because of the ambiguity you mention and because the ‘match’ runs up against the back of the return type.
Just to throw it out there, I think the true ideal syntax for this is
That is, no special syntax at all to set off the match and not requiring parens for the argument tuple. I believe this is unambiguous b/c ‘=>’ isn’t used for anything else, but I haven’t seriously proposed it b/c the parser lookahead and magic tupling seem like things that would get a lot of pushback.
The other alternative I was thinking of was something like
Hilarious brain fart aside: this is similar to how many years ago I consistently read (Brent) 'Scowcroft' as 'Snowcroft', to the point where I was tremendously confused and rather agitated by the fact that if I wrote the name into Google myself, it only returned a single result, while if I copy pasted the name from a web page, it returned lots of results. It took me a while to realize what was going on and that the world hadn't stopped making sense, only my brain.
Similarly, in this case for years now I had been under the impression that the => operator used by Rust for match and by Haskell for type class contexts is the greater-than-or-equals operator, and specifically thinking that this would likely end up causing some problems for Haskell when the type system advanced to the point that they got to writing inequality comparisons at the type level.
...but it turns out that >= and => are distinct entities.
Is there something specific about the doubled brackets you don't like?
It seems awfully arbitrary and not very aesthetically appealing (line noise, etc.).
For language features like this, my request is that if they incur overhead in the compiler (I don’t know how much there actually would be), there should be a way to disable them. This and other features (like if let) might be things I just decide not to use, e.g. for simplicity and consistency reasons (one of the great things about C is how dead simple the language is, not just for computer to parse, but for humans, too!). If I can squeeze out any more compiler performance by not using more sugary language features, I’d absolutely like that option.
Simplicity is in the eyes of the beholder, I guess. C is simple but a lot of C programs end up being verbose and complex b/c the language isn’t expressive enough. Compact forms for common idioms lead to simpler programs (though admittedly it can be taken too far).