On Thu, Mar 14, 2019 at 7:42 PM Theodore Brown <theodor...@outlook.com> wrote: > > On Thu, March 14, 2019 10:41 AM Nikita Popov <nikita....@gmail.com> wrote: > > > On Wed, Mar 13, 2019 at 4:56 PM Nikita Popov <nikita....@gmail.com> wrote: > > > > > Hi internals, > > > > > > Motivated by the recent list comprehensions RFC, I think it's time we took > > > another look at short closures: > > > > > > https://wiki.php.net/rfc/arrow_functions_v2 > > > > As a small update, I've implemented a proof of concept that uses the ($x) > > ==> $x * $multiplier syntax (or $x ==> $x * $multiplier for short) in > > https://github.com/php/php-src/pull/3945. As mentioned in the RFC, this > > requires scanahead in the lexer. > > > > This syntax is in principle still on the table, though personally I prefer > > fn($x, $y) => $x * $y over ($x, $y) ==> $x * $y. The main redeeming quality > > of ==> is that it supports the paren-less variant $x ==> $x. Taking into > > account the lexer hackery it requires (and which will also be required in > > any 3rd party tooling), this would not be my preferred choice. > > > > I agree that the nicest thing about this syntax is the ability to save > an additional 3 characters of boilerplate for the common use case of > single-parameter arrow functions. However, I'm also not a fan of adding > complex code hacks to make the syntax work. > > One alternative that doesn't seem to have had much discussion on list > is the `\($x) => $x * $y` lambda syntax. This would also allow parentheses > to be omitted for single parameters, making it just as terse as the ==> > syntax without the need for any lexer hackery. > > Here's how the examples from the RFC would look: > > ```php > function array_values_from_keys($arr, $keys) { > return array_map(\$x => $arr[$x], $keys); > } > > > $extended = \$c => $callable($factory($c), $c); > > > $this->existingSchemaPaths = array_filter($paths, \$v => in_array($v, > $names)); > > > function complement(callable $f) { > return \(...$args) => !$f(...$args); > } > > > $result = Collection::from([1, 2]) > ->map(\$v => $v * 2) > ->reduce(\($tmp, $v) => $tmp + $v, 0); > ``` > > One argument against this shorter syntax is that it wouldn't be as > easy to google as `fn`. However, long term I think everyone would > still get used to it, and I'm personally willing to add an answer > to the top Stack Overflow search result for "php backslash keyword". > > The backslash syntax has precedent from Haskell, and also wouldn't > introduce any BC break (who knows how many private codebases might > already have functions named `fn`). > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
I'd certainly be on board with the fn() syntax, but the backslash syntax has definitely grown on me. To me, all of the examples in Theodore's email are very readable and I find that the backslash makes it very easy to identify arrow functions when grokking. array_filter($numbers, \$n => $n % 2); vs. array_filter($numbers, fn($n) => $n % 2); When grokking these two pieces of code, I immediately see "\$n => $n % 2" as a single unit, whereas in the latter example I instinctively (and incorrectly) interpret "fn($n)" as an expression. When parens are required, the difference is obviously reduced, but I think I still prefer the backslash syntax since the LHS doesn't grok as a function call. reduce($numbers, \($x, $y) => $x + $y); vs. reduce($numbers, fn($x, $y) => $x + $y); That said, I'd personally take either syntax gladly. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php