The Pipe Operator

Read the RFC Externals
90
262 yes
122 no

The "pipe operator" |> allows you to chain multiple function calls in a more convenient way.

$result = "Hello World"
    |> 'htmlentities'
    |> 'str_split'
    |> fn($x) => array_map('strtoupper', $x)
    |> fn($x) => array_filter($x, fn($v) => $v != 'O');

This RFC was already declined, but we're sharing it here as another test RFC, and because it'd be interesting to learn people's opinion about it.

Click the bar to cast your vote!
68%
32%
83

With First-class callable syntax available since 8.1, it would now be possible to write it as below, which is much better then string names of functions:

$result = "Hello World"
    |> htmlentities(...)
    |> str_split(...)
    |> fn($x) => array_map(strtoupper(...), $x)
    |> fn($x) => array_filter($x, fn($v) => $v != 'O');
Share:
pronskiy avatar
pronskiy
voted yes
64

For me, the most important argument is that the pipeline pattern is a tried and tested pattern, that this RFC builds upon. A couple of examples:

This RFC adds syntax to make using these kinds of pattern much more convenient.

On top of that, there's the argument that multiple modern languages support a pipe operator:

Finally, I've had numerous occasions where a pipe operator would simplify my own code — I have more than a handful real life cases where this would be useful.

Share:
Contributor brent avatar
brent
voted yes
33

I see no immediate benefit of the proposed solution over the userland implementations. The RFC mentions a shopping cart example, but I don't think that's cleaner than using league/pipeline or Laravel's pipeline.

It's a bit messy for the simpler examples as well.

Share:
ju5t avatar
ju5t
voted no
23

For example:

$result = "Hello World"
    |> 'htmlentities'
    |> 'str_split'
    |> fn($x) => array_map('strtoupper', $x)
    |> fn($x) => array_filter($x, fn($v) => $v != 'O');

Is 'nicer' since it has better readability and clearer syntax than:

$result = array_filter(
        str_split(
            strtoupper(
                htmlentities("Hello World")
            )
        ),
        fn($v) => $v != '0'
    );
Share:
josebenraul avatar
josebenraul
voted yes
22

I could have used it multiple times for array transformations. But the RFC still built on really ancient PHP behaviour (mapping functions as strings) and should be redone by fosucing only on modern syntax:

  • closures and short closure: |> fn($x) => array_filter($x, fn($v) => $v != 'O')
  • first class callable syntax: |> str_split(...)
Share:
tpetry avatar
tpetry
voted yes
16

Still hard to read. No extra benefits.

The only clean solution is to use scalar types (string, int, float, boolean) and arrays like objects:

$result = "Hello World"->htmlentities()->split()->map(strtoupper(...))->filter(fn($v) => $v != 'O');

Chain, clean oop, readable, IDE hint, no value parameter, no prefixes and an opportunity to correct the functions inconsistency. It could works beside functions: strtoupper($name) and $name->toUpper().

Share:
hricer avatar
hricer
voted no
15

It's almost as messy as putting all the functions into each other.

Share:
t avatar
t
voted no
15

The idea is a nice one, and one that I would welcome, but this proposal puts forward messy syntax that isn't clear!

Share:
ollieread avatar
ollieread
voted no
11

I think complaints about the syntax being messy are really about the array manipulation functions being inherently hard to format nicely.

To be clear I agree that the proposed example isn't great, nested closures are never going to win any readabillity prizes. If however we look at any non-array based manipulation I think the readabillity is objectively better:

$name = 'my_user_name'
    |> fn (string $string): string => str_replace('_', ' ', $string)
    |> strtolower(...)
    |> ucwords(...)
    |> trim(...);

Or without first class callables:

$name = 'my_user_name'
    |> fn (string $string): string => str_replace('_', ' ', $string)
    |> fn (string $string): string => strtolower($string)
    |> fn (string $string): string => ucwords($string)
    |> fn (string $string): string => trim($string);

Bonus: this also adds runtime type checks to each step. Eg strreplace returns string|array

I can't imagine anyone would think this is better:

$name = trim(
    ucwords(
        strtolower(
            str_replace('_', ' ', 'my_user_name')
        )
    )
);
Share:
moebrowne avatar
moebrowne
voted yes
6

I think this would be a great improvement.

I prefer this:

$result = "Hello World"
    |> htmlentities(...)
    |> str_split(...)
    |> fn($x) => array_map(strtoupper(...), $x)
    |> fn($x) => array_filter($x, fn($v) => $v != 'O');

instead of this:

$result = "Hello World"
    |> 'htmlentities'
    |> 'str_split'
    |> fn($x) => array_map('strtoupper', $x)
    |> fn($x) => array_filter($x, fn($v) => $v != 'O');
Share:
william-2 avatar
william-2
voted yes
6

this syntax is unclear, and functions who gets multiple arguments will not be properly supported.

Share:
roeycohen avatar
roeycohen
voted no
6

No clear benefit and the syntax is simply just too messy.

Share:
D avatar
D
voted no
3

need it

Share:
shtiher-pp avatar
shtiher-pp
voted yes
3

This will help make code more readable in situations when we have to chain many built-in functions and is a good entrypoint for making pure minimalistic functions a first class citizen in PHP.

Share:
khalyomede avatar
khalyomede
voted yes
2

Maybe if the function names didn't need to be in quotes... As it is certainly not.

Share:
enumag avatar
enumag
voted no

Check out another RFCs

new MyClass()->method() without parentheses

Chain method on newly created objects without parentheses

29
38 yes
13 no
Property Hooks

A new way of interacting with properties

63
121 yes
78 no
Interface Default Methods

Interface Default Methods improves backwards compatibility when changing interfaces, but also add a way to have multi-inheritance in PHP.

95
168 yes
263 no
RSS Feed Contribute Watch on YouTube Our License
© 2024 RFC Vote. This project is open source. Contribute and collaborate with us!