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

Reply via email to