Re: [RFC] Pipe Operator
| From: | François Laupretre | Date: | Sun, 01 May 2016 11:57:21 +0000 |
| Subject: | Re: [RFC] Pipe Operator | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-93018@lists.php.net to get a copy of this message | ||
Ho Rowan,
Le 01/05/2016 01:14, Rowan Collins a écrit :
On 29/04/2016 20:58, Sara Golemon wrote:I find your suggestion brilliant, including ending with a 'return' statement. Just a question : do we really need a different operator ? I may be wrong but '|> $ret' or '|> return $$' doesn't seem ambiguous to me (the parser should be able to recognize an assignable LHS or 'return'). I even suggest we use a '... |> $var |> ...' syntax to assign intermediate variables. I am currently writing a message proposing a way to complement these 'piped calls' with a way to get rid of the '$$' placeholder. This will address the long-running sadness of argument order. Regards FrançoisThis is one of my favorites out of HackLang. It's pure syntactic sugar, but it goes a long way towards improving readability. https://wiki.php.net/rfc/pipe-operatorI like this idea, for the same reason I like chained method calls - the code reads left to right, rather than inside to outside. One problem with that, though, is that the output from the whole expression ends up on the left, if you want to save it out somewhere. To take an example from the RFC: $ret = scandir($arg)|> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |> getFileArg($$) |> array_merge($ret, $$);Once you've read through this whole sequence of steps, you have to go right back to the beginning to find that the result is saved into "$ret". It's not clear to me whether the RHS in the current implementation can be an arbitrary expression, since all the examples use function calls at every step; would this be valid? scandir($arg)|> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |> getFileArg($$) |> array_merge($ret, $$) |> ($ret = $$);Even if it is, it looks a bit ugly; what about adding an extra operator for assignment, like "|>=" or "|=>"? scandir($arg)|> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |> getFileArg($$) |> array_merge($ret, $$) |=> $ret;I think this would also improve the situation around debugging and error-handling, because you could more freely mix piped and non-piped code by "breaking the chain" with an assigment. Let's say I want to add a condition just before getFileArg(); with the current version I've got to: - go to the beginning of the chain, and assign to something other than $ret - go to where I want to break the chain, and reintroduce the $ret assignment - add my check in the gap, using the variable I just added at the beginning of the chain $fileList = scandir($arg)|> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; },$$); if ( someCheck($fileList) {something();} $ret = getFileArg($$)|> array_merge($ret, $$);The syntax is fighting me here, making me jump around the code. But if assignment was always on the end of the chain, I would only need to make changes at the point where I was breaking the chain. The basic pattern would be: |=> $tempVar; // terminate the chain and capture the value // do stuff with $tempVar $tempVar // restart the chain So: scandir($arg)|> array_filter($$, function($x) { return $x !== '.' && $x != '..'; }) |> array_map(function ($x) use ($arg) { return $arg . '/' . $x; }, $$) |=> $fileList;if ( someCheck($fileList) {something();} $fileList|> getFileArg($$) |> array_merge($ret, $$) |=> $ret;If I don't need the condition any more, I can delete lines 4 to 8, and I've got back my original chain. Again, I'm not clear from the RFC if it's currently valid to use "return" in a piped expression, but it makes sense to me for the same reasons outlined above. This example is from the Hack docs, where it puts the "return" on the left, breaking the flow: return $arr|> array_map($x ==> $x->getNumber(), $$) |> array_filter($$, $x ==> $x % 2 == 0) |> count($$);To me, that reads better as: $arr|> array_map($x ==> $x->getNumber(), $$) |> array_filter($$, $x ==> $x % 2 == 0) |> count($$) |> return $$;Personally, I'd quite like it if the chain *had* to have a left-to-right form like this, and always constituted a statement, not an expression. Regards,