@ 2019-04-24T14:55:40Z

<?php // WARNING: this is just a way to experiment with short closures and you SHOULD NOT write code like this echo '# PART 1 - Short closures may contain only 1 expression and nothing more'.PHP_EOL.PHP_EOL; // Two expressions: Syntax error (not catchable in this branch) // $test = fn($x) => { $y = 10; return $x + $y; }; function last(...$args) { // all expression results enter here return end($args); // only last one is returned } // unlike JavaScript where the last expression is returned, PHP returns a boolean $andOperator = fn($x) => ($y = 10) && $x + $y; var_dump($andOperator(7)); // PHP also doesn't have a comma operator like JS. In JS "a, b" will return b // $commaOperator = fn($x) => $y = 10, $x + $y; // Syntax error // end() only accepts references, so no luck yet: //$arrayEnd = fn($x) => end([$y = 10, $x + $y]); // Fatal error: Only variables can be passed by reference $multipleLines = fn($x) => last( $y = $x * 10, $z = $y + 15, $x + $y + $z // result of this line is returned from last() ); var_dump($multipleLines(7)); $moreComplex = fn($x) => last( $numbers = range(0, $x), $y = array_map(fn($z) => strlen($z), $numbers), array_sum($y) // result of this line is returned from last() ); var_dump($moreComplex(7)); echo PHP_EOL; echo '# PART 2 - Short closures bind by value, always'.PHP_EOL.PHP_EOL; function walkThisWay(Closure $closure) { // just an example $i = 0; while ($word = $closure()) { echo $word.PHP_EOL; $i++; if ($i > 3) { // length of $parameters echo 'NAH! it seems it\'s not really a reference'.PHP_EOL; break; } } echo PHP_EOL; } echo "## TEST 1 - not a reference:".PHP_EOL; $parameters = ['banana', 'terracotta', 'pie']; // we want to change $parameters, but what we have is a copy of it, arrays behave this way walkThisWay(fn() => array_shift($parameters)); echo "## TEST 2 - syntax error:".PHP_EOL; $parameters = ['banana', 'terracotta', 'pie']; // Error is not catchable in this branch //walkThisWay(fn() use (&$parameters) => array_shift($parameters)); echo PHP_EOL; echo "## TEST 3 - object:".PHP_EOL; $parameters = ['banana', 'terracotta', 'pie']; $wrapper = (object) ['parameters' => &$parameters]; // objects are not really references, but they know where all data is, a copy is not made // You could also use ArayObject instead of $wrapper walkThisWay(fn() => array_shift($wrapper->parameters)); echo "## TEST 4 - functional hack:".PHP_EOL; $parameters = ['banana', 'terracotta', 'pie']; function ref(&$reference, Closure $closure) { return function (...$args) use ($closure, &$reference) { $args[] = &$reference; // add a reference to $parameters in the arguments return $closure(...$args); }; } walkThisWay(ref($parameters, fn(&$parameters) => array_shift($parameters))); echo "## TEST 5 - good old functions (better use this version in real code):".PHP_EOL; $parameters = ['banana', 'terracotta', 'pie']; walkThisWay(function () use (&$parameters) { return array_shift($parameters); });