Re: [RFC] Pipe Operator (again)

From: Date: Thu, 03 Apr 2025 11:58:46 +0000
Subject: Re: [RFC] Pipe Operator (again)
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
On 03/04/2025 08:22, Larry Garfield wrote:
However, it also received significant pushback off-list from folks who felt it was too much magic. I don't want to torpedo pipes on over-reaching. But without feedback from other voters, I don't know if this is over-reaching. Is it? Please, someone tell me which approach you'd be more willing to vote for. :-)
At first, I thought Ilija's example looked pretty neat, but having thought about it a bit more, I think the "first-arg" approach makes a handful of cases nicer at the cost of a lot of magic, and making other cases worse. The right-hand side is magic in two ways: 1) it looks like an expression, but actually has to be a syntactic function call for the engine to inject an argument into 2) it looks like it's calling a function with the wrong arguments If we have a special case where the right-hand side *is* an expression, evaluated as a single-argument callable/Closure, that's even more scope for confusion. [cf my thoughts in the async thread about keeping the right-hand side of "spawn" consistent] The cases it makes nicer are where you are chaining existing functions with the placeholder as first (but not only) parameter. If you want to pipe into a non-first parameter, you have a few options: a) Write a new function or explicit wrapper - equally possible with either option // for first-arg chaining: function swapped_explode(string $string, string $separator): string { return explode($separator, $string); } $someChain |> swapped_explode(':'); // for only-arg chaining: function curried_explode(string $separator, string $string): callable { return fn(string $string) => explode($separator, $string); } $someChain |> curried_explode(':'); b) Use an immediate closure as the wrapper - only-arg chaining seems better // first-arg chaining $someChain |> fn($string) => explode(':', $string)(); // first-arg chaining with special case syntax for closures $someChain |> ( fn($string) => explode(':', $string) ); // for only-arg chaining: $someChain |> fn($string) => explode(':', $string); c) Use a new partial application syntax - same problem as immediate closure // for first-arg chaining $someChain |> explode(':', ?)(); // or with overloaded syntax $someChain |> ( explode(':', ?) ); // for only-arg chaining $someChain |> explode(':', ?); It's also quite easy to write a helper for the special-case of "partially apply all except the first argument": function partial_first(callable $fn, mixed ...$fixedArgs): callable {
    return fn(mixed $firstArg) => $fn($firstArg, ...$fixedArgs);
} // first-arg chaining $someChain |> array_filter(fn($v, $k) => $k === $v, ARRAY_FILTER_USE_BOTH); // native partial application $someChain |> array_filter(?, fn($v, $k) => $k === $v, ARRAY_FILTER_USE_BOTH); // workaround $someChain |> partial_first(array_filter(...), fn($v, $k) => $k === $v, ARRAY_FILTER_USE_BOTH)); -- Rowan Tommins [IMSoP]

Thread (38 messages)

« previous php.internals (#127032) next »