# Optional closure syntax

**URL:** <https://internals.rust-lang.org/t/optional-closure-syntax/22188>\
**Category:** language design\
**Created:** [January 20, 2025, 10:11pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188 "2025-01-20T22:11:58Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![NonSecwitter](https://avatars.discourse-cdn.com/v4/letter/n/b77776/32.png) [@NonSecwitter](https://internals.rust-lang.org/u/NonSecwitter)\
**Post date:** [January 20, 2025, 10:11pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/1 "2025-01-20T22:11:58Z")

</div>

This is more of a light musing than passionate appeal, so I won't be debating this vigorously, but I thought I'd offer it as a suggestion.

I learned closures and function literals through Scala, and compared to the Rust syntax, I appreciate the clarity of the Scala syntax provided by the separator between parameters and body.

```scala
val addFunc = (x: Int, y: Int) => x + y

```

An identical definition in Rust would be

```rust
let addFunc = |x: i32, y: i32| x + y

```

I like the use of `=>` in Scala to separate the parameter declaration from the function body. I realize that this operator is already in use for `match`, so a non-starter there, but I think there is an opportunity to use an unused operator such as `~>` in its place.

```rust
let addFunc = |x: i32, y: i32| ~> x + y

```

I suggest this because, even as someone who understands and recognizes the closure syntax, the current syntax looks like a run-on sentence; to me the `|` doesn't sufficiently differentiate the parameters from the body and it looks like a single expression. The use of an arrow operator, to me, indicates that `| THESE THINGS |` are doing `~> this() + stuff()`

I also realize that ergonomics is an objective for Rust, but I think two characters is reasonable.

Finally, by making it optional, you avoid breaking changes, although I would be curious to see usage statistics down the road if implemented.

Anyway, just wanted to make a passing suggestion. I'm not a language expert or anything, so take this with a grain of salt.

Cheers

---

<div class="post-metadata">

**Author:** ![binarycat](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/binarycat/32/12210_2.png) [@binarycat](https://internals.rust-lang.org/u/binarycat)\
**Post date:** [January 20, 2025, 10:20pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/2 "2025-01-20T22:20:27Z")

</div>

rust already uses an arrow for the return type of a closure.

`|x: u8, y: u8| -> u8 { x + y }`

---

<div class="post-metadata">

**Author:** ![NonSecwitter](https://avatars.discourse-cdn.com/v4/letter/n/b77776/32.png) [@NonSecwitter](https://internals.rust-lang.org/u/NonSecwitter)\
**Post date:** [January 20, 2025, 10:30pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/3 "2025-01-20T22:30:20Z")

</div>

Ah yea, I forgot the return type. I guess in that case it would be more

```rust
|x: i32, y:i32| -> i32 ~> x + y

```

Scala has the benefit of not using an arrow for return type

```scala
(x: Int, y: Int): Int => x + y

```

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 20, 2025, 10:46pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/4 "2025-01-20T22:46:49Z")

</div>

Please note that [changes to (existing) syntax](https://lang-team.rust-lang.org/frequently-requested-changes.html#fundamental-changes-to-rust-syntax) are a (relatively) frequently requested thing, and have a relatively high bar for actually being accepted.

 

It’s almost impressive how much of that section (click the link above 😉) seems to apply here

> These also include proposals to add "alternative" syntaxes, in addition to those that replace the existing syntax. Many of these proposals come from people who also write other languages. Arguments range from the ergonomic ("I don't want to type this") to the aesthetic ("I don't like how this looks").

* * *

I appreciate your thoughts and do myself sometimes feel like Rust’s choice is a bit weird, coming from functional languages myself, which all like some forms of arrows; but in the end, once used to it, I find this syntax works just as well, too.

I’m also regularly surprised by _how_ much variety syntax for anonymous function really offers across programming languages… heck, even in mathematics, there’s very far from a single consistent syntax for defining a quick “helper function” [one of the most common I’ve seen would be to use the “↦” operator; but also many will just prefer to _always_ give a function a name, anyway].

I wonder, just out of curiosity, is there a good writeup giving an overview of the different kinds of closure/lambda/anonymous-function syntaxes in programming languages out there? And does Rust’s `|args| expr` syntax come from the specific precedent of some (or multiple) other languages?

* * *

> [@NonSecwitter](#):
>
> I suggest this because, even as someone who understands and recognizes the closure syntax, the current syntax looks like a run-on sentence; to me the `|` doesn't sufficiently differentiate the parameters from the body and it looks like a single expression.

Do note that a closure _is_ “a single expression”, though that’s probably not what you meant. Also, as far as I’m aware, the style enforced by `rustfmt` is anyways for any case of a _multi-line_ closure to wrap the RHS in a block… which IMO generally suffices to make sure the closure is hard to miss syntactically.

In fact, thinking back to examples like Haskell\[1\] with the multi-line case in mind, I find perhaps that’s the biggest strength of the arrow-less syntax… at the end of a line, a right-arrow to “nothing” just looks a bit silly, e.g. compare

```rust
(0..100).for_each(|i| {
    let x = i * i;
    println!("{i} squared is {x}");
});

```

to something like this proposal’s

```rust
(0..100).for_each(|i| ~> {
    let x = i * i;
    println!("{i} squared is {x}");
});

```

* * *

> [@NonSecwitter](#):
>
> Finally, by making it optional, you avoid breaking changes, although I would be curious to see usage statistics down the road if implemented.

I don’t think bringing _even more_ optionality into closure syntax is necessarily a great idea. There’s already the optional type signatures for arguments; optional specification of the return type; the option to wrap the RHS in a block or not; and even some subtle interactions of these optionalities\[2\]

* * *

1. E.g. when conventionally desugaring “`do` notation”, you might get code such as

2. if you do specify a return type, then the block becomes part of the closure syntax itself, which has subtle operator precedence consequences, e.g. `|x| -> Ty { …block… }.some_method()` vs `|x| { …block… }.some_method()` applying `some_method` outside of the closure to the whole closure, or inside of it only to the returned block

---

<div class="post-metadata">

**Author:** ![NonSecwitter](https://avatars.discourse-cdn.com/v4/letter/n/b77776/32.png) [@NonSecwitter](https://internals.rust-lang.org/u/NonSecwitter)\
**Post date:** [January 20, 2025, 10:58pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/5 "2025-01-20T22:58:11Z")

</div>

That's fair, and the syntax is manageable, just not aesthetically pleasing. I guess with the consideration of block syntax as option on the RHS, I'd probably advocate for making that required rather than introducing another arrow on top of the return type arrow. But, I suspect changing a syntax from optional to required is less likely to happen than my original suggestion, so I will simply curse under my breath every time I read and write it 🙂

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 20, 2025, 11:03pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/6 "2025-01-20T23:03:08Z")

</div>

I’m just realizing, … something you could _totally_ do in your own code at least … if you simply _always_ use the closure syntax with “explicit” return type, even leaving the return type explicitly inferred via `_`, that gives you _some_ presence of an arrow; and also forces the presence of braces with it, too 😁

Whichever you prefer from

```rust
let addFunc = |x, y| -> _ { x + y };

```

or

```rust
let addFunc = |x: i32, y: i32| -> _ { x + y };

```

or

```rust
let addFunc = |x: i32, y: i32| -> i32 { x + y };

```

Add to this the explicit `()` for closures “without” a return value, and that might be some nice explicitness, too 🤔

```rust
(0..100).for_each(|i| -> () {
    let x = i * i;
    println!("{i} squared is {x}");
});

```

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [January 23, 2025, 11:32pm UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/7 "2025-01-23T23:32:35Z")

</div>

> [@steffahn](#):
>
> does Rust’s `|args| expr` syntax come from the specific precedent of some (or multiple) other languages?

It's Ruby I believe.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [January 24, 2025, 1:58am UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/8 "2025-01-24T01:58:57Z")

</div>

Ruby is (IMO) substantially different: the `|args|` goes on the inside of the braces, not before them.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [July 18, 2026, 1:59am UTC](https://internals.rust-lang.org/t/optional-closure-syntax/22188/9 "2026-07-18T01:59:27Z")

</div>

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
