I think so! At least until method-style function calls land in Roc, but possibly even after that. I've seen it mentioned several times that |> (also known as the pipe operator, or jokingly pizza :pizza:) can/should be removed from Roc with WSA, but I'm skeptical of that. Since it's one of Roc's most recognizable operators (and personally one of my favorite elements of its syntax), I'd like us to fully reconsider it (and its family of related operators like .) in the context of the syntax changes coming this year.
I think pipe shines best in multi-line pipelines. Here's an example I've used in previous topics...
main! = |_|
"./input.txt"
|> Path.from_str
|> try Path.read_bytes!
|> try Foo.from_bytes
|> transform(2, Much)
|> try Foo.to_bytes
|> Path.write_bytes!(Path.from_str("./output.txt"))?
Stdout.line!("🥳 See ./output.txt")
to ask about how we expect multi-line function call chains might look when method-style function calls land with static dispatch in several months after the compiler rewrite:
main! = |_|
"./input.txt"
.(Path.from_str)
.read_bytes!?
.(Foo.from_bytes)?
.(transform)(2, Much)
.to_bytes?
.(Path.write_bytes!)(Path.from_str("./output.txt"))
Stdout.line!("🥳 See ./output.txt")
It seems that .(local_fn) (also known as the "pass to" syntax) could be a one-to-one replacement for most pipes. However, I'm unclear whether folks want .(local_fn) to be that ubiquitous, and suspect that there are many circumstances where having a non-method-style function chaining syntax is desirable.
Does anyone have an example of PNC+SD code that feels better as PNC+SD+:pizza:?
The main problem is precedence, how do you make |> work with method calls in a way that doesn't look weird?
data = start.call() |> local_func.next_method()
You'd have to make a space-based operator bind the same as dots
Also, the current plan is for (from an old example).method().other() to act as sugar for |x| x.method().other()
I will agree that from an Elm/FP-in-general background, I much prefer the reading of |> over the .(local_func)(args) thing
With the recent whitespace discussions, we could make |> always add newlines to the whole chain, turning the above to
data =
start.call()
|> local_func
.next_method()
Which I believe is less confusing
I realize I may be in the minority on this, but I really like being able to do:
time = 4.(hours).(ago!)
and I like that a lot better than
time = 4 |> hours |> ago!
I'm not a big fan of .(fn)(arg) but I don't have a great alternative idea either
I do like . being the consistent chaining/autocomplete character, and I do like the precedence being more straightforward and easy to understand
If it weren't even more parens, I'd like it more
But the alternatives we discussed weren't great either
I'm considering throughout these discussions that most function chains should be methods anyway
So all these examples with |> or .(func) are good at showing how these would look when used in volume
But they inflate the perceived frequency of these tools
to be fair though, I'm also not a fan of multi-arg PNC with pipe:
|> fn(arg1, arg2)
that super doesn't look like a function that is being passed 3 arguments :sweat_smile:
and yet it is
I'd say val.method(arg1, arg2) is the same thing, we're just used to it
But we're used to it so...
fair!
but yes, I am used to it and it doesn't look weird to me :laughing:
Richard Feldman said:
I realize I may be in the minority on this, but I really like being able to do:
time = 4.(hours).(ago!)and I like that a lot better than
time = 4 |> hours |> ago!
I totally agree. I really like the .() syntax in general for local calls
I'm not a big fan of
.(fn)(arg)but I don't have a great alternative idea either
I remember .$ and .. came up as options a couple times. arg1..fn(arg2). Were they ever ruled out?
.$ is getting some re-evaluation in #ideas > static dispatch - pass_to alternative , along with discussion of all alternatives for the method-style syntax version of |>
This seems like consensus to fully remove |> by not implementing it in the new compiler.
For deprecation, I propose matching whatever is decided in #contributing > deprecating WSA (whitespace application for function calls) but without any pre-v0.1.0 PRs because the replacement syntax won't work before then.
Last updated: Jun 16 2026 at 16:19 UTC