On Thursday 14 August 2025 21:30:08 (+02:00), Larry Garfield wrote:
> Does anyone have a better solution to suggest?
I've been following the discussion on the pipe/short-closure precedence
issue, and while the parentheses-based solution works, it does lead to
syntactic noise that undermines the readability benefits of pipes.
I'd like to suggest an alternative that turns this problem into an
opportunity for a more elegant syntax.
Inspired by prior art like Haskell's `do` notation, I propose what I
call "short closure canned pipes." The idea is to leverage the greedy
nature of short closures to define a clean, linear pipe chain within a
closure context. Instead of fighting the precedence, we embrace it to
create a new form:
Current problematic example (even with parentheses):
----------------------------------------------------
fn($x) => ($x
|> (fn($x) => array_map(strtoupper(...), $x))
|> (fn($x) => array_filter($x, fn($v) => $v != 'O'))
);
Proposed "canned pipes" syntax:
-------------------------------
fn($x) =>
|> array_map(strtoupper(...), $x)
|> array_filter($x, fn($v) => $v != 'O')
;
This syntax:
* Resolves the ambiguity: The `fn($x) =>` explicitly "cans" the value
for the entire pipe chain, making the precedence clear without
parentheses.
* Reduces boilerplate: It eliminates the repetition of `fn($x) =>` and
nested parentheses, making the code more readable and maintainable.
* Aligns with intent: It reads as a simple sequence of transformations,
which is the core goal of the pipe operator.
This approach effectively provides syntactic sugar for the common case
of processing a value through a pipe chain within a closure. It turns
the late-discovered defect into a win for developer ergonomics and
future-proofing.
I understand that implementation feasibility needs to be assessed, but
if possible, this could be a more satisfying solution than mandatory
parentheses. Thanks to the team for highlighting this issue -- it's
sparked a creative way to enhance the feature.
Would love to hear thoughts on this.
Best,
hakre