Pipe Operator
This is actually part of an ongoing sequence of syntax improvements that started back with $a = foo(...); for creating closures. There is more to come in this area.
Back in the day, I inflicted something like
$file = array_map(fn($line) => explode(' ', $line), array_values(
array_filter(
array_map(trim(...),
preg_split('/\b0\b/',
join(' ',
array_map(collapse_space(...),
array_map(trim(...),
preg_grep('/^\s*-?\d+(\s+-?\d+)*\s*$/',
preg_grep('/^[a-z]/',
file($filename),
PREG_GREP_INVERT))))),
flags: PREG_SPLIT_NO_EMPTY)),
strlen(...))));
on you all. Notice how far some of the arguments end up from the function call they're actually part of.
With the pipe operator that becomes
$file = file($filename)
|> (fn($ls) => preg_grep('/^[a-z]/', $ls, PREG_GREP_INVERT))
|> (fn($ls) => preg_grep('/^\s*-?\d+(\s+-?\d+)*\s*$/', $ls))
|> (fn($ls) => array_map(trim(...), $ls))
|> (fn($ls) => array_map(collapse_space(...), $ls))
|> (fn($ls) => join(' ', $ls))
|> (fn($ls) => preg_split('/\b0\b/', $ls, flags: PREG_SPLIT_NO_EMPTY))
|> (fn($ls) => array_map(trim(...), $ls))
|> (fn($ls) => array_filter($ls, strlen(...)))
|> array_values(...)
|> (fn($ls) => array_map(fn($line) => explode(' ', $line)));
Which is definitely easier to follow. Still a bit verbose, but like I say the syntax changes are a work in progress.