Proposal. Pipeline assignment operator

php.internals

Vadim Dvorovenko

1 year ago
Recently introduced pipeline operator is great, but together with assignment operator it will lead to mixing top-to-bottom and bottom-to-top code reading directions and vertigo. To reduce this problem i'd like to discuss the idea of left to right assignment operator. The draft rfc can be found here https://github.com/vadimonus/php-rfc-pipeline-assignment/blob/main/rfc.md , there is the part, that describes problem. It currently has one question (can we use |> also for assignment?), that would be better to discuss before 8.5 release, to avoid later breaking changes. If someone like the idea, i need wiki rfc creation rights to create rfc. I do not think it would be to hard to implement it, as it is just another syntax for existing operator, and should lead to exactly same bytecode. I could try to implement for 8.6 release (not sure it is possible to implement it in 8.5 as it is already in alpha, but if it is possible, maybe someone will decide to quickly implement it for 8.5).

Niels Dossche

1 year ago
Hi Vadim The example where |> is used to assign to a variable seems not possible to me. It will lead to an ambiguity when $result is a callable for example. Therefore, |>= is the only possibility of the two your proposed. Kind regards Niels

Ilija Tovilo

1 year ago
Hi Vadim Thanks for your follow-up. On Sun, Jul 20, 2025 at 11:54 AM Vadim Dvorovenko <vadim.dvorovenko@gmail.com> wrote:
> > Recently introduced pipeline operator is great, but together with > assignment operator it will lead to mixing top-to-bottom and > bottom-to-top code reading directions and vertigo. > > To reduce this problem i'd like to discuss the idea of left to right > assignment operator. The draft rfc can be found here > https://github.com/vadimonus/php-rfc-pipeline-assignment/blob/main/rfc.md > , there is the part, that describes problem.
The problem you're describing is not unique to pipes. Code like this is quite common. $x = foo() ->bar() ->baz(); If we decide this is a problem (which I fundamentally disagree with), then we should try to find a general solution, rather than something that is specific to pipes. There's no reason why this example shouldn't work. foo() ->bar() ->baz() |>= $x; At that point, you should probably also look for an operator that isn't pipe-specific. But again, I disagree with the premise that this is a problem to begin with.
> The current bahavior of pipe operator when used with variable is wery poorly described in RFC
That's not quite accurate. It states:
> The left-hand side of the pipe may be any value or expression.
And according to PHPs expression model, variables get no special treatment. They are evaluated and the result is used accordingly, pipes are not special at all in that regard. Cheers Ilija

Larry Garfield

1 year ago
On Sun, Jul 20, 2025, at 5:22 AM, Ilija Tovilo wrote:
> Hi Vadim > > Thanks for your follow-up. > > On Sun, Jul 20, 2025 at 11:54 AM Vadim Dvorovenko > <vadim.dvorovenko@gmail.com> wrote: >> >> Recently introduced pipeline operator is great, but together with >> assignment operator it will lead to mixing top-to-bottom and >> bottom-to-top code reading directions and vertigo. >> >> To reduce this problem i'd like to discuss the idea of left to right >> assignment operator. The draft rfc can be found here >> https://github.com/vadimonus/php-rfc-pipeline-assignment/blob/main/rfc.md >> , there is the part, that describes problem. > > The problem you're describing is not unique to pipes. Code like this > is quite common. > > $x = foo() > ->bar() > ->baz(); > > If we decide this is a problem (which I fundamentally disagree with), > then we should try to find a general solution, rather than something > that is specific to pipes. There's no reason why this example > shouldn't work. > > foo() > ->bar() > ->baz() |>= $x; > > At that point, you should probably also look for an operator that > isn't pipe-specific. But again, I disagree with the premise that this > is a problem to begin with. > >> The current bahavior of pipe operator when used with variable is wery poorly described in RFC > > That's not quite accurate. It states: > >> The left-hand side of the pipe may be any value or expression. > > And according to PHPs expression model, variables get no special > treatment. They are evaluated and the result is used accordingly, > pipes are not special at all in that regard. > > Cheers > Ilija
I am also not a fan of this proposal for much the same reason. First, the mental model it proposes I do not agree with. The model of <variable to assign to> = <arbitrarily complex expression> is fairly universal in PHP and in most languages. It's quite self evident at this point. Furthermore, there are plenty of other "read down and up" use cases beyond pipe. match() and ternaries come to mind as common examples. The behavior of pipes with variables is also very well defined. The left side is any expression (including a variable). The right side is a callable. That callable could be a variable that references a Closure, and often will be. So it's already quite clear what will happen If we were to agree that there was a use case for "reverse assignment" (of which I am not yet convinced), it should be its own stand-alone thing. Just for argument's sake (not actually proposing this): <expression> ==> <variable to assign to> That would then work at the end of a pipe chain, a match statement, a ternary, or whatever else you felt like. Self-contained parts that play well with others are almost always superior to a one-off solution. --Larry Garfield

Vadim Dvorovenko

1 year ago
Sorry, that's my first reply to mailing list discussion, maybe i'm not doing it right. Ilija wrote:
> The problem you're describing is not unique to pipes. Code like this > is quite common. $x = foo() ->bar() ->baz(); If we decide this is a > problem (which I fundamentally disagree with), then we should try to > find a general solution, rather than something that is specific to > pipes. There's no reason why this example shouldn't work. foo() > ->bar() ->baz() |>= $x; At that point, you should probably also look > for an operator that isn't pipe-specific. But again, I disagree with > the premise that this is a problem to begin with.
You're providing some fluent-like syntax as example of situation. Foobar example does not show all posible use cases. Compare, two code blocks, they are read differently even same syntax. // no need to replace with pipe operator. // you even will not try to wrap such code to improve readability. Little chance structure will change in future, order of call could not be changed. // no need of left to right assignment in this case. Little chancethat expression will grow more than 2-3 lines. $x = $movies->getMovie()->getCharacters()->getCharacter() // complex structure access, inspired by (inspired by https://www.php.net/manual/en/simplexml.examples-basic.php) $y = collect($strings)->trim()->toUpper()->implode(','); // Fluent chain of calls. this case is what pipe operator for. // you will probably want to wrap this line to improve readability. Order of processing is point of further changes. List can grow, leading to 10-15 lines of piped function calls, if some map calls or other transformations are added. In fluent we even can write foo()->bar()->baz()->assignTo($x) (as it's user-defined method, we can make any logic). With fluent we do not need nor pipe, nor ltr-assignment. But someone thought fluent syntax is not good, as this is not native language operator, but a wrapper pattern, and we have pipe operator now. But we must remember that fluent syntax appeared precisely because the language did not have tools to record the order of calls from left to right and top to bottom. From a programming language perspective, fluent syntax is just a chain of calls. The appearance of such an language element as the pipe operator in the programming language proves that the need for reading the calls from left to the right existed. And this need is dictated precisely by our perception of the code, and not by some technical need. This also proves that we have same need of left-to-right assignment operator, caused by same feature of human perception. My proposal is about need of left to right assignment operator together with left to right function call operator. As idea was inspired by pipe operator rfc, so i chosed operator most looked like pipe. If the pipe symbol distracts from the essence, lets' discuss some other symbol, e.g. --> $x --> $y; $strings   |> 'trim'   |> 'toUpper'   |> implode(',', ...)   --> $y foo() ->bar() ->baz() --> $x;
>> The current bahavior of pipe operator when used with variable is wery poorly described in RFC > That's not quite accurate. It states: > >> The left-hand side of the pipe may be any value or expression. > And according to PHPs expression model, variables get no special > treatment. They are evaluated and the result is used accordingly, > pipes are not special at all in that regard. >
You're speaking about left-hand side of operator. I'm speaking about case, where variable is in the right side of pipe operator. RFC contains no examples, where there's variable, storing callable. Even without my proposal, this should be clarified in documentation on pipe operator. Expression $x |> $y can mislead.

Tim Düsterhus

1 year ago
Hi Am 2025-07-20 21:31, schrieb Vadim Dvorovenko:
> In fluent we even can write foo()->bar()->baz()->assignTo($x) (as it's > user-defined method, we can make any logic). With fluent we do not need > nor pipe, nor ltr-assignment. But someone thought fluent syntax is not > good, as this is not native language operator, but a wrapper pattern, > and we have pipe operator now.
FWIW: You can also define such an `assign_to()` function for use with pipes. See https://3v4l.org/R5b2f/rfc#vgit.master: function assign_to(&$var) { return function ($value) use (&$var) { $var = $value; }; } $string = "Hello World!"; $string |> strtolower(...) |> ucfirst(...) |> assign_to($result); var_dump($result); Best regards Tim Düsterhus