Re: Re: [RFC][Discuss] Arrow Functions
| From: | Larry Garfield | Date: | Sat, 04 Feb 2017 20:49:53 +0000 |
| Subject: | Re: Re: [RFC][Discuss] Arrow Functions | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-98196@lists.php.net to get a copy of this message | ||
On 02/03/2017 11:53 AM, Levi Morrison wrote:
Off hand, either of the above options would be acceptable to me. The union type concern is a valid one, but as noted I don't know how much of an issue that would be in practice even if we ever did get union types. (Now, if we also added defined type aliases... :-) ) I am definitely not a fan of reusingThanks to everyone who has participated in the discussion thus far. Primarily the feedback has been directed at theOne more thing: I'd like to re-emphasize that the syntax that JavaScript uses and the one that HHVM/Hack uses are ambiguous in the current class of our grammar. The following will not work unless we move to a more powerful grammar and parser class:fnkeyword. Let me provide two benefits and drawbacks of usingfnas a keyword: 1.fnis searchable in search engines and in our manual 2. Is more intuitive than just syntax However,fndoes have downsides: 1. Can break existing code 2. We already have a similar keywordfunctionTo that end, I'd like to gauge interest in a pure syntax based alternative that is similar to Rust and Ruby. Instead of:fn(params) => exprWhat about:|params| => exprThis trades the advantages of the keyword for the advantages of pure syntax, and happens to be two characters shorter. To be explicit:1. Preserves 100% backwards compatibility 2. Avoids having two keywords that both mean "function" 3. Is not easily searchable in engines or in the manual 4. Is a tad bit shorterWhat do you think, Internals?(params) => expr (params) ==> exprThis is why an un-ambiguous prefix is necessary: the prefix breaks the ambiguities. The syntax I have suggested in the RFC and the one I suggested just now are not ambiguous because distinct prefixes:fn(params) => expr |params| => exprI look forward to more discussion!
function. The way I see it, the point of a short-closure is to take a simple expression and wrap it into a function so that it can be plugged into a function context. I don't even think of it in the same way I would a named function/method, more casting an expression to a function.
Additionally, to the point that was raised about developers being able to understand syntax reused in different context, that's true... if the context is in fact different. A bitwise AND and a reference are extremely different situations so there's no reason for my brain to expect both to mean the same thing. One is never a viable substitute for the other.
In contrast, however, we're talking about two different syntaxes for defining anonymous functions that have different closure semantics. Reusing function would mean:
$n = 2;
$x = function ($a) use ($n) { return $a * $n; }
$y = function ($a) => $a * $n;
Are equivalent. But in order to know what the capture semantics are I can't tell from the start of the expression. I have to look halfway down the line to know what the behavior is going to be for these two extremely similar actions.
In contrast:
$n = 2;
$x = function ($a) use ($n) { return $a * $n; }
$y = fn($a) => $a * $n;
$z = |$a| => $a * $n;
I in versions $y and $z, I can tell right from the beginning of the line which variant of "anonymous function capture logic" I will be dealing with. I know from character 1 or 2, not character 12.
And then there's the extra typing and visual space taken up, which is not something to dismiss entirely. Also, as someone else mentioned this syntax *seems* like it would support nesting. Compare the following:
$x = function($a) => function($b) => function($c) => $a * $b * $c;
$y = fn($a) => fn($b) => fn($c) => $a * $b * $c;
$z = |$a| => |$b| => |$c| => $a * $b * $c;
print $x(1)(2)(3); // prints 6
Which of these is more readable? Id' argue it's not $x.
--Larry Garfield