This is an old revision of the document!

PHP RFC: Pipe Operator


Complex nested expressions can become progressively difficult to read the deeper they go with function returns leading into arguments to functions which return an argument to another call and so on and so forth. This RFC aims to improve code readability by decomposing complex nested expressions into a series of linearly readable chained statements.


Introduce the “Pipe Operator” `|>`, a binary expression which uses the result of the LHS as an input to the RHS expression at an arbitrary point denoted by the additional “Pipe Replacement Variable” expression `$$`. The result of the RHS expression, after substitution, is used as the result of the operator.

This feature is being culled from HackLang 3.13 and the manual page for it may be referenced at: https://docs.hhvm.com/hack/operators/pipe-operator

As an example, consider the following real block of code I wrote while creating a test importer (to migrate HHVM format tests into PHPT format):

$ret = 
        function ($x) { return $arg . '/' . $x; },
          function ($x) { return $x !== '.' && $x !== '..'); }

This block of code is readable, but one must carefully examine the nesting to determine what the initial input it, and what order it traverses the steps involved.

With this proposal, the above could be rewritten as:

$ret = scandir($arg)
    |> array_filter($$, function($x) { return $x !== '.' && $x != '..'; })
    |> array_map(function ($x) { return $arg . '/' . $x; }, $$)
    |> getFileArg($$)
    |> array_merge($ret, $$);

This clearly, and unambiguously shows `scandir()` as the initial source of data, that it goes through an `array_filter` to avoid recursion, an `array_map` to requalify the paths, some local function, and finally a merge to combine the result with a collector variable.

Backward Incompatible Changes

While most ambiguities of `$$` between pipe replacement variable and variable variables are covered in the lexer rule, the following case is not accounted for:

$a = 1;
$b = 'a';
var_dump($$ /* comment */ {'b'});
// Expected: int(1)
// Actual: Use of $$ outside of a pipe expression

This particular quirk of the parser (allowing comments in the middle of a variable-variable-brace-expression is doubtlessly a rare occurance in the wild, so the current implementation stopped short of trying to resolve it.

Potential resolutions:

  • Use a less-ambiguous token. `$>` which mirrors `|>` is my personal favorite. Downshot: doesn't match HackLang
  • Get very creative in the parser. Since '$' '{' expr '}' is handled by the parser, then perhaps '$' '$' should as well. So far, attempts to resolve this result in conflicts. More work may yet yield results.

Proposed PHP Version(s)


Open Issues

See BC issues

Future Scope

The current proposal limits use of the `$$` to a single replacement per expression. This feature could potentially be expanded to allow multiple uses of `$$` within a single RHS expression.

Proposed Voting Choices

Adopt the PIpe Operator yes/no? Requires a 2/3 + 1 majority.

Patches and Tests

rfc/pipe-operator.1461959802.txt.gz · Last modified: 2017/09/22 13:28 (external edit)