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"
Are these features you hope roc accepts or just exploration?
It is both. I would love to see my exploration converts to the actual feature.
Isn't \x -> x |> foo just foo?
Sky Rose said:
Isn't
\x -> x |> foojustfoo?
true but if foo has more than one argument then \x -> x |> foo y isn't the same as foo y
You may want to break this into a few different proposals. For example the binary when separate from unary dot separate from closure shorthand.
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.
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.
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