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
>
> This is based on a previous (withdrawn) proposal by Levi & Bob. It uses
> the syntax
>
>     fn($x) => $x * $multiplier
>
> and implicit by-value variable binding. This example is roughly equivalent
> to:
>
>     function($x) use($multiplier) { return $x * $multiplier; }
>
> The RFC contains a detailed discussion of syntax choices and binding modes.
>

Trying to reply to everyone in one mail...

1. Using f() =>. This is possible. However, f would become a reserved
keyword, and I'm very leery of making a single-character reserved keyword.
Additionally I think that the fn() => syntax is more intuitive, but maybe
that's my Rust influences speaking ;)

2. $this binding. Yes, $this is indeed bound exactly as with normal
closures. I've explicitly mentioned this in the RFC now.

3. yield. Using yield is per-se not a problem. You can write `() => yield
42`, which is basically `function() { return yield 42; }`, which is okay,
because yield is an expression and generators can return values since PHP
7. It also doesn't seem particularly useful though, as you're limited to
yielding a single value.

However, in the current form short closures are a replacement for list
comprehensions only insofar they make the use of map() and filter()
non-torturous. You couldn't actually use them to get a comprehension-like
syntax as suggested in the other thread:

    $gen = (fn() => foreach ($list as $elem) yield $elem * 2))();
    // would be, hypothetically:
    $gen = (function() use($list) { return foreach ($list as $elem) yield
$elem * 2; }))();

The yield part here isn't the problem, "return foreach" is. Unlike yield,
foreach is a statement, not an expression. To make this work we'd need a
block form of short closures:

    $gen = (fn() { foreach ($list as $elem) yield $elem * 2; })();
    // or maybe

    $gen = (fn() => { foreach ($list as $elem) yield $elem * 2; })();

Either way, I wouldn't want to read that code ;) The right way to write
this is $list->map(fn($elem) => $elem * 2).

4. ($x) => $x instead of $x => $x. As Rowan mentioned, this doesn't really
change things. Where $x is valid, ($x) is in most cases also valid.

Regards,
Nikita

Reply via email to