On Sat, Sep 26, 2015 at 10:17 AM, Levi Morrison <le...@php.net> wrote:
> (Email in gist format:
> https://gist.github.com/morrisonlevi/fa7984c04ff176b5a87c)
>
> In EcmaScript 2015 (ES6) the expression `(x) => x * 2` means to create
> an anonymous function with one parameter `x` that will return `x * 2`.
> For example:
>
>     (x) => x * 2
>     // is equivalent to:
>     function(x) { return x * 2; }
>
> A modified example from [documentation by Mozilla Developer
> Network][1] page demonstrates how they are useful:
>
>     var a = [
>         "Hydrogen",
>         "Helium",
>         "Lithium",
>         "Beryl­lium"
>     ];
>
>     var a2 = a.map(function(s){ return s.length }); // pre-ES6
>
>     var a3 = a.map((s) => s.length); // ES6
>
> There has been some talk about how we can use arrow function
> expressions in PHP. In PHP using the same syntax would have some
> ambiguities:
>
>     // Does this mean:
>     //   1. Create an array key with the result of `($x)` and a value
> with `$x * 2`
>     //   2. Create an array with one value that is an anonymous function
>     [($x) => $x * 2]
>
>     // Does this mean:
>     //   1. Yield a key with the result of `($x)` and a value with `$x * 2`
>     //   2. Yield an anonymous function
>     yield ($x) => $x * 2;
>
> This is why Bob Weinand [proposed][2] using `~>` instead of `=>`.
> However, if we allow type declarations there is another issue. In the
> definition `(Type &$x) => expr` the `(Type &$var)` part can parse as
> "take constant `Type` and variable `$var` and do a bitwise and `&`
> operation." After that the `=>` will be an unexpected token. Even
> though the rule would be invalid the parser doesn't know that far
> ahead it will error and it doesn't know which rule to pick. Changing
> the token from `=>` to `~>` doesn't affect this issue.
>
> We could solve the first ambiguities with prefering the current
> meaning with `key => value` and requiring the meaning with closures to
> wrap them in `()`. We could solve the latter ambiguity with a
> backtracking parser since it will eventually error and then know to
> pick the other rule. However, I really think this is a bad idea.
>
> So how can we have shorter closures without this mess? One simple way
> is to require the `function` prefix:
>
>     // clearly an array with an anonymous function
>     [function($x) => $x * 2];
>
>     // clearly yields an anonymous function
>     yield function($x) => $x * 2;
>
>     // clearly an anonymous function
>     function(Type &$x) => expr;
>
> Requiring the `function` prefix mitigates one of the value parts of
> arrow functions: they are short.
>
> Another option would be to resolve the ambiguities with keys and
> values but to change the type information in parameters:
>
>     (&$input: array) => expr
>
> By putting the type after the variable (similar to how we declare
> return types) we no longer have the issues with mis-parsing. Of
> course, that's not how we declare parameter types currently. I think
> we would need to permit it everywhere and deprecate the current syntax
> with the type being prefixed. (By deprecate I mean in PHP 8 and not
> remove it until PHP 9 or later)
>
> I would prefer that we shorten the `function` keyword to `fn`:
>
>     [fn($x) => $x * 2]
>
> This preserves the shortness of the expression while providing
> unambiguous, simple parsing. Of course, now we have a similar issue:
> we have both `fn` and `function`.
>
> What concerns do you have about `fn($x) => $x * 2` or `function($x) =>
> $x * 2`? I will be writing a proper RFC later but I wanted to get
> discussion going now.
>
>   [1]: 
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
>   [2]: https://wiki.php.net/rfc/short_closures

I forgot to mention that the arrow expressions would close over any
values that exist in their parent scope. Like Bob's proposal this
happens by value (in fact the draft I have for it simply replaces the
parser and reuses his implementation):

    function add($x) {
        return fn($y) => $x + $y;
    }

    add(1)(2); // int(3)

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to