# Match fn sugar

**URL:** https://internals.rust-lang.org/t/match-fn-sugar/431
**Category:** ideas (deprecated)
**Created:** [August 26, 2014, 7:38pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431 "2014-08-26T19:38:55Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [August 26, 2014, 7:38pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/1 "2014-08-26T19:38:55Z")

</div>

This has probably been brought up before but I couldn’t find the magic github/google query to find a previous discussion.

A fairly common pattern is for a fn to immediately wrap a match expr, like so:

```
fn foo(x: Option<int>, y: Option<int>) -> Option<int> {
    match (x, y) {
        (Some(x), Some(y)) => Some(x + y),
        (Some(x), None) => Some(x),
        _ => None
    }
}

```

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:

```
match fn foo(Option<int>, Option<int>) -> Option<int> {
    (Some(x), Some(y)) => Some(x + y),
    (Some(x), None) => Some(x),
    _ => None
}

```

This compares pretty nicely with the equivalent Haskell:

```
foo :: Maybe Int -> Maybe Int -> Maybe Int
foo (Just x) (Just y) = Just (x+y)
foo (Just x) _ = Just x
foo _ _ = Nothing
```

---

<div class="post-metadata">

### Author: ![reem](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/reem/32/167_2.png) [@reem](https://internals.rust-lang.org/u/reem)
#### Post date: [August 27, 2014, 8:13am UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/2 "2014-08-27T08:13:43Z")

</div>

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](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.

---

<div class="post-metadata">

### Author: ![xcv](https://avatars.discourse-cdn.com/v4/letter/x/e68b1a/32.png) [@xcv](https://internals.rust-lang.org/u/xcv)
#### Post date: [August 27, 2014, 9:57am UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/3 "2014-08-27T09:57:02Z")

</div>

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:

```rust
let getJust = \case
  Just x -> x
  Nothing -> error "getJust: Nothing"
```

Rust:

```rust
let get_just = match {
  Some(x) => x
  None => fail!("get_just: None")
};
```

---

<div class="post-metadata">

### Author: ![tomjakubowski](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tomjakubowski/32/4876_2.png) [@tomjakubowski](https://internals.rust-lang.org/u/tomjakubowski)
#### Post date: [August 27, 2014, 11:48am UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/4 "2014-08-27T11:48:24Z")

</div>

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](http://is.gd/cYPwA2)):

```rust
#![feature(macro_rules)]

macro_rules! matchfn {
    ($name:ident ($($arg:ident : $arg_ty:ty),+) -> $fn_ty:ty {
        $($pat:pat => $rhs:expr),+
    }) => {
        fn $name($($arg : $arg_ty),+) -> $fn_ty {
            match ($($arg),+) {
                $($pat => $rhs),+
            }
        }
    }
}

matchfn!(foo(_a: Option<int>, _b: Option<int>) -> Option<int> {
    (Some(x), Some(y)) => Some(x + y),
    (Some(x), None) => Some(x),
    _ => None
})

pub fn main() {
    println!("{}", foo(Some(12), Some(24)));
    println!("{}", foo(Some(36), None));
    println!("{}", foo(None, None));
}

```

---

<div class="post-metadata">

### Author: ![phaylon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phaylon/32/62_2.png) [@phaylon](https://internals.rust-lang.org/u/phaylon)
#### Post date: [August 27, 2014, 4:06pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/5 "2014-08-27T16:06:00Z")

</div>

Actually, you can omit the argument names if you walk the list of types and build up the signature and the match tuple along the way: [playpen link](http://is.gd/IZf4y7)

---

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [August 27, 2014, 4:54pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/6 "2014-08-27T16:54:37Z")

</div>

That’s pretty sweet. Only seems to work w/ exactly two args right now, though.

---

<div class="post-metadata">

### Author: ![phaylon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/phaylon/32/62_2.png) [@phaylon](https://internals.rust-lang.org/u/phaylon)
#### Post date: [August 27, 2014, 5:28pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/7 "2014-08-27T17:28:36Z")

</div>

Was a typo, here’s a fix: [playpen](http://is.gd/WjqYMx). 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.

---

<div class="post-metadata">

### Author: ![mdinger](https://avatars.discourse-cdn.com/v4/letter/m/97f17d/32.png) [@mdinger](https://internals.rust-lang.org/u/mdinger)
#### Post date: [August 29, 2014, 5:37pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/8 "2014-08-29T17:37:18Z")

</div>

If this happens there probably could also be other variants:

```rust
loop fn foo() {...}
loop match fn foo(Option<int>, Option<int>) -> Option<int> {...}

```

Also, if it could handle methods too:

```rust
fn next(&mut self) {
    match self.state {
        _ => {};
    };
}

```

Then [this](http://blog.piston.rs/2014/08/29/inside-the-game-loop/) could be reduced by 2 nesting levels. There could possibly be more variants (`while;for;if/else`) if there was a workable scheme.

---

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [October 17, 2014, 1:31pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/9 "2014-10-17T13:31:51Z")

</div>

Another thought is demarcating a match block in ‘arg receiver position’ using doubled brackets (or whatever):

```
fn foo(x: Option<int>, y: Option<int>) -> Option<int> {{  
    (Some(x_), Some(y_)) => Some(x_+y_),  
    (Some(x_), None) => Some(x_),
    _ => None
}}

```

The advantage of this is that it extends naturally to closures:

```
|x, y| {{
    (Some(x_), Some(y_)) => Some(x_ + y_),
    (Some(x_), None) => Some(x_),
    _ => None
}}

```

And impls can more closely match trait signatures:

```
trait Foo {
    fn foo(&self, x: Option<int>) -> Option<int>;
}

impl Foo for Option<int> {
    fn foo(&self, x: Option<int>) -> Option<int> {{
        (&Some(x_), Some(y_)) => Some(x_ + y_),
        (&Some(x_), None) => Some(x_),
        _ => None        
    }}
}
```

---

<div class="post-metadata">

### Author: ![liigo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/liigo/32/454_2.png) [@liigo](https://internals.rust-lang.org/u/liigo)
#### Post date: [October 18, 2014, 7:24am UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/10 "2014-10-18T07:24:05Z")

</div>

No a very useful use case.

---

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [October 18, 2014, 9:41am UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/11 "2014-10-18T09:41:21Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)
#### Post date: [October 18, 2014, 12:28pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/12 "2014-10-18T12:28:54Z")

</div>

I like the idea, but of course not the particular syntax. I would prefer something like:

```
fn foo(x: Option<int>, y: Option<int>) -> Option<int> match {  
    (Some(x_), Some(y_)) => Some(x_+y_),  
    (Some(x_), None) => Some(x_),
    _ => None
}

```

where conceptually the whole function is a `match` block.

Unfortunately if we go to extend this to lambdas, it’s slightly ambiguous:

```
|x, y| match {
    (Some(x_), Some(y_)) => Some(x_ + y_),
    (Some(x_), None) => Some(x_),
    _ => None
}

```

The problem is that `{`…`}` is itself an expression. Is it the match scrutinee or the body?

---

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [October 18, 2014, 2:22pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/13 "2014-10-18T14:22:42Z")

</div>

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

```
fn foo(x: Option<int>, y: Option<int>) -> Option<int> {  
    Some(x_), Some(y_) => Some(x_+y_),  
    Some(x_), None => Some(x_),
    _ => None
}

```

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

```
fn foo(x: Option<int>, y: Option<int>) -> Option<int> {=>  
    (Some(x_), Some(y_)) => Some(x_+y_),  
    (Some(x_), None) => Some(x_),
    _ => None
}

```

But that’s another magic sigil.

Is there something specific about the doubled brackets you don’t like? Is it just the lack of explicitly saying ‘match’?

---

<div class="post-metadata">

### Author: ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)
#### Post date: [October 18, 2014, 11:27pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/14 "2014-10-18T23:27:16Z")

</div>

> [@jfager](#):
>
> I believe this is unambiguous b/c '=\>' isn't used for anything else

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

---

<div class="post-metadata">

### Author: ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)
#### Post date: [October 19, 2014, 1:53pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/15 "2014-10-19T13:53:00Z")

</div>

On Sat, Oct 18, 2014 at 12:44:50PM +0000, glaebhoerl wrote:

---

<div class="post-metadata">

### Author: ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)
#### Post date: [October 19, 2014, 2:03pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/16 "2014-10-19T14:03:10Z")

</div>

Discourse ate your reply :\

---

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [October 19, 2014, 3:38pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/17 "2014-10-19T15:38:38Z")

</div>

Working off @mdinger’s comment, more match sugar:

```
for v in foo.iter() {{
    (Some(x), Some(y)) => println!("Total: {}", x+y),  
    (Some(x), None) => println!("x: {}", x),
    _ => println!("no x")
}} 

loop rx.recv() {{
    (Some(x), Some(y)) => println!("Total: {}", x+y),
    (Some(x), None) => println!("x: {}", x),
    _ => println!("no x")
}}

```

Or more like @glaebhoerl’s alternative:

```
for match v in foo.iter() {
    (Some(x), Some(y)) => println!("Total: {}", x+y),  
    (Some(x), None) => println!("x: {}", x),
    _ => println!("no x")
} 

loop match rx.recv() {
    (Some(x), Some(y)) => println!("Total: {}", x+y),
    (Some(x), None) => println!("x: {}", x),
    _ => println!("no x")
}

```

I think ‘if let’ and ‘while let’ are already the analogous sugar for ‘if’ and ‘while’.

---

<div class="post-metadata">

### Author: ![bfops](https://avatars.discourse-cdn.com/v4/letter/b/50afbb/32.png) [@bfops](https://internals.rust-lang.org/u/bfops)
#### Post date: [October 19, 2014, 7:24pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/18 "2014-10-19T19:24:53Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![Drup](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/drup/32/128_2.png) [@Drup](https://internals.rust-lang.org/u/Drup)
#### Post date: [October 19, 2014, 7:28pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/19 "2014-10-19T19:28:02Z")

</div>

FWIW, In OCaml, the sugar is the following:

```rust
let f = function 
 | ....

```

is (exactly) the same as

```rust
let f x = match x with
 | ...

```

---

<div class="post-metadata">

### Author: ![jfager](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jfager/32/156_2.png) [@jfager](https://internals.rust-lang.org/u/jfager)
#### Post date: [October 19, 2014, 8:09pm UTC](https://internals.rust-lang.org/t/match-fn-sugar/431/20 "2014-10-19T20:09:12Z")

</div>

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

[Next page](https://internals.rust-lang.org/t/match-fn-sugar/431.md?page=2)
