Re: Arrow function expressions in PHP
| From: | Bob Weinand | Date: | Wed, 30 Sep 2015 12:52:56 +0000 |
| Subject: | Re: Arrow function expressions in PHP | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-88579@lists.php.net to get a copy of this message | ||
> Am 26.9.2015 um 18:17 schrieb Levi Morrison <levim@php.net>:
>
> (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",
> "Beryllium"
> ];
>
> 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
Hey,
Thanks a lot for your thoughts on it.
I think unlike a lot of critics in the original thread, this actually is a viable solution.
As I mentioned, I’d prefer fn($x) => $x ** 2 as general short Closure syntax (no alias to
function), for better distinguishing from the normal Closures.
Alternatively, Objective-C has also an interesting syntax with a leading ^ (instead of your
function).
But, as long as we want types etc, we definitely need a prefix (as long as we don’t want ugly
parser hacking) … And in general, the prefix also provides better recognizability that it actually
should be a short Closure [Also a reason why I dislike reusing function as prefix here].
May you please set up a formal RFC for that in the wiki so that I may withdraw my current RFC in
favor of yours, which, I think, honestly is a superior solution as it addresses types and as said,
might be easier to recognize at a quick glance.
[And also obsoletes a lot of complaints about the operator … Seems more people than expected
actually dislike ~> ...]
Thanks,
Bob