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

Reply via email to