On Thu, Aug 21, 2025, at 15:53, Larry Garfield wrote: > On Thu, Aug 21, 2025, at 4:07 AM, Hans Krentel wrote: > > 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 > > That's an interesting idea, but I don't think it solves the problem. > > It would make the syntax for pipes-in-closures nicer, yes. However: > > 1. Ideally, I'm hoping such a pipe-in-closure is replaced with a Composition > operator soon enough (https://wiki.php.net/rfc/function-composition), so that > wouldn't even be necessary. > 2. The main problem is not when a pipe is inside a closure, but when a > closure is inside a pipe, which is likely the far more common case. > > $input > |> fn($x) => array_map(strtoupper(...), $x) > |> fn($x) => array_filter($x, fn($v) => $v != 'O') > ; > > The problem is this gets interpreted "backwards", with the first closure > wrapping around second, rather than being a sibling of it in a pipe chain. A > short-hand for pipes-in-closures wouldn't address this issue, which is the > more pressing concern. > > The annoying extra parens there would also be resolved using PFA, which side > steps the arrow function in the common case. As the issue is the syntactic > parsing of arrow functions, not having arrow functions would also resolve the > issue. (As would using higher-order functions instead, which frankly is what > I am likely to do 90% of the time myself.) > > --Larry Garfield >
I think the point Hans was making is that the fn($x) becomes implicit so you don't even need it, so your example would be something like this in this case: $input |> fn($x) => |> array_map(strtoupper(...), $x) |> array_filter($x, fn($v) => $v != 'O'); — Rob