Re: Re: [RFC][Discuss] Arrow Functions

From: 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:
Thanks to everyone who has participated in the discussion thus far. Primarily the feedback has been directed at the fn keyword. Let me provide two benefits and drawbacks of using fn as a keyword: 1. fn is searchable in search engines and in our manual 2. Is more intuitive than just syntax However, fn does have downsides: 1. Can break existing code 2. We already have a similar keyword function To 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) => expr
What about:
     |params| => expr
This 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 shorter
What do you think, Internals?
One 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:
     (params) => expr
     (params) ==> expr
This 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| => expr
I look forward to more discussion!
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 reusing 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

« previous php.internals (#98196) next »