Stream: ideas

Topic: Closure shortcut feature


view this post on Zulip Maksim Volkau (Nov 10 2024 at 22:17):

I wanted to learn Roc compiler and add a fun feature, a syntax sugar for the closure of single argument with pipe,
where this code \|> foo translates to \x -> x |> foo.

From this intent, emerged a general idea of the "closure shortcut" for the binary and unary operators, record field and tuple accessors, identity function. The feature is implemented on the level of Parser, and it does not tax other parts of compiler. Underneath the AST is the same, with some small markers for the shortcut nodes.

The other side of this feature is the Formatter. By default, roc format will keep the shortcut syntax.
But you may guide it to expand the shortcut into the full closure form.
Say you've typed \|> shortcut, then you can put space between opening \ and |> in \ |> foo and it will expand into \x -> x |> foo on format (automatically with format-on-save and auto-save enabled in the editor).

So it provides editor-like quick snippet functionality in the language itself, which I did not see anywhere else.

The idea is implemented already as part of this PR and you can play with it right now :-) More details and examples in the PR description.

Related ideas: #ideas > Syntax sugar for "piped when"?, #ideas > Shorthands for nested records

Examples:

Binary operators:

List.map [1, 2, 3] \|> foo
List.map [1, 2, 3] \+ 1

Record fields and tuple accessors:

List.map [{ foo: 1 }] \.foo
List.map [(bar, 5)] \.0
List.map [{ foo: {bar: (x, y)}}] \.foo.bar.1

Identity function:

List.map [1, 2, 3] \.

Unary operators:

List.map [1, 2, 3] \-.
List.map [x, y] \!.

Combinations:

List.map [x, y] \-.foo.bar + 1

Binary operator for the when pattern matching:

foo ~
    "abc" -> ""
    _ -> "abc"

When operator as closure shortcut:

\~
    "abc" -> ""
    _ -> "abc"

Combines with the rest:

\.foo + 1 ~
    "abc" -> ""
    _ -> "abc"

view this post on Zulip Brendan Hansknecht (Nov 10 2024 at 22:57):

Are these features you hope roc accepts or just exploration?

view this post on Zulip Maksim Volkau (Nov 10 2024 at 23:04):

It is both. I would love to see my exploration converts to the actual feature.

view this post on Zulip Sky Rose (Nov 10 2024 at 23:24):

Isn't \x -> x |> foo just foo?

view this post on Zulip Derin Eryilmaz (Nov 10 2024 at 23:24):

Sky Rose said:

Isn't \x -> x |> foo just foo?

true but if foo has more than one argument then \x -> x |> foo y isn't the same as foo y

view this post on Zulip Brendan Hansknecht (Nov 10 2024 at 23:46):

You may want to break this into a few different proposals. For example the binary when separate from unary dot separate from closure shorthand.

view this post on Zulip Brendan Hansknecht (Nov 10 2024 at 23:47):

I will warn that roc tends to focus on readability in a way that generally does not match this proposal. So it is probably pretty unlikely to be accepted.

view this post on Zulip Maksim Volkau (Nov 11 2024 at 08:28):

I would like to keep this feature together, as a complete package.
Parts of this feature combine in "natural" way and it is hard to discuss separately.
Also, it covers the questions "what about?" - If dot field access supported, what about dot alone? If binary op is supported, what about unary? Etc.

view this post on Zulip Maksim Volkau (Nov 11 2024 at 16:33):

Update: I have added Formatter side of the feature into the description, which I forgot last night. Now it should provide the full picture together with the PR.


Last updated: Jun 16 2026 at 16:19 UTC