Re: [PHP-DEV] [RFC] Arrow functions / short closures

This is only part of a thread. view whole thread
  104711
March 14, 2019 13:44 rowan.collins@gmail.com (Rowan Collins)
On 13 March 2019 15:56:40 GMT+00:00, Nikita Popov ppv@gmail.com> wrote:
>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
Hi Nikita, Thanks for reviving this. I think the RFC does a great job of justifying both the syntax and the behaviour, and focusing on the most used features without ruling out further additions in future. In particular, I think whether and how we support auto-capture in full function bodies has its own pros and cons to debate, separate from auto-capture as a convenience in short "lambda" expressions. I was initially quite drawn to a block-style syntax. As someone not particularly familiar with functional programming (which I suspect puts me in the majority of PHP users), I actually find it easier to spot this as "a closure returning a closure": { ($x) => { ($y) => $x * $y } } rather than having to work out the associativity of chained operators: fn($x) => fn($y) => $x * $y However, I imagine the only people who will heavily use such a construct will be those who *are* familiar with functional programming in other languages, and will find the simpler syntax more familiar and convenient. It would also be ugly to add full block bodies in a similar style like { ($x) => { ... } }, and while I'm not convinced we need that, we probably don't want to rule it out completely. As such, I support the RFC in its current form. Regards, -- Rowan Collins [IMSoP]
  104713
March 14, 2019 14:12 benjamin.morel@gmail.com (Benjamin Morel)
This makes me thinking, has this syntax been considered?

($x) => { $x * $y }

Nested:

($x) => { ($y) => { $x * $y } }

AFAICS, we don't need the brackets around the whole expression, as this
should be parsable without any ambiguity; and the syntax would be closer to
that of JavaScript.


On Thu, 14 Mar 2019 at 14:44, Rowan Collins collins@gmail.com> wrote:

> On 13 March 2019 15:56:40 GMT+00:00, Nikita Popov ppv@gmail.com> > wrote: > >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 > > Hi Nikita, > > Thanks for reviving this. I think the RFC does a great job of > justifying both the syntax and the behaviour, and focusing on the most > used features without ruling out further additions in future. In > particular, I think whether and how we support auto-capture in full > function bodies has its own pros and cons to debate, separate from > auto-capture as a convenience in short "lambda" expressions. > > I was initially quite drawn to a block-style syntax. As someone not > particularly familiar with functional programming (which I suspect > puts me in the majority of PHP users), I actually find it easier to > spot this as "a closure returning a closure": > > { ($x) => { ($y) => $x * $y } } > > rather than having to work out the associativity of chained operators: > > fn($x) => fn($y) => $x * $y > > However, I imagine the only people who will heavily use such a > construct will be those who *are* familiar with functional programming > in other languages, and will find the simpler syntax more familiar and > convenient. > > It would also be ugly to add full block bodies in a similar style like > { ($x) => { ... } }, and while I'm not convinced we need that, we > probably don't want to rule it out completely. > > As such, I support the RFC in its current form. > > Regards, > -- > Rowan Collins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  104714
March 14, 2019 14:54 rowan.collins@gmail.com (Rowan Collins)
On Thu, 14 Mar 2019 at 14:12, Benjamin Morel morel@gmail.com>
wrote:

> This makes me thinking, has this syntax been considered? > > ($x) => { $x * $y } > > Nested: > > ($x) => { ($y) => { $x * $y } } >
Wouldn't this have all the same parser problems as the RFC discusses? The problem, as I understand it, is not avoiding ambiguity, it's avoiding lookahead. If you write: $foo = [ ($x) => { $x } ]; $bar = [ ($x) => $x ]; The parser has already consumed " [ ($x) =>" before it can decide if each ($x) is an array key or a closure signature. It's parseable, but only using one of the workarounds described in the RFC. If I'm understanding the RFC correctly, the only way to avoid that is to have closures *start* differently from other valid constructs, because then the parser doesn't need to recurse / backtrack / etc. Regards, -- Rowan Collins [IMSoP]
  104715
March 14, 2019 15:09 benjamin.morel@gmail.com (Benjamin Morel)
> > The problem, as I understand it, is not avoiding ambiguity, it's avoiding > lookahead.
You're right, I was only thinking about resolving the ambiguity with array keys. It's too bad if the parser implementation considerations take precedence over the purity of the language, but I can understand the maintenance nightmare that people are trying to avoid here. Something else that crosses my mind, is: what prevents us from using the same syntax as ES6: ($x) => $x * $y But to prevent any ambiguity, forbid array keys from being enclosed with parenthese? For example, the following would be considered an array containing a closure: [ ($foo) => "bar" ] And the following would just become a syntax error: [ ("foo") => "bar" ] Would that solve the parser problem? BC-wise, I don't think this would be much of a problem: I have yet to see array keys enclosed with parentheses in PHP codebases. On Thu, 14 Mar 2019 at 15:54, Rowan Collins collins@gmail.com> wrote:
> On Thu, 14 Mar 2019 at 14:12, Benjamin Morel morel@gmail.com> > wrote: > > > This makes me thinking, has this syntax been considered? > > > > ($x) => { $x * $y } > > > > Nested: > > > > ($x) => { ($y) => { $x * $y } } > > > > > Wouldn't this have all the same parser problems as the RFC discusses? > > The problem, as I understand it, is not avoiding ambiguity, it's avoiding > lookahead. If you write: > > $foo = [ ($x) => { $x } ]; > $bar = [ ($x) => $x ]; > > The parser has already consumed " [ ($x) =>" before it can decide if each > ($x) is an array key or a closure signature. It's parseable, but only using > one of the workarounds described in the RFC. > > If I'm understanding the RFC correctly, the only way to avoid that is to > have closures *start* differently from other valid constructs, because then > the parser doesn't need to recurse / backtrack / etc. > > Regards, > -- > Rowan Collins > [IMSoP] >
  104719
March 14, 2019 15:49 rowan.collins@gmail.com (Rowan Collins)
On Thu, 14 Mar 2019 at 15:10, Benjamin Morel morel@gmail.com>
wrote:

> The problem, as I understand it, is not avoiding ambiguity, it's avoiding >> lookahead. > > > You're right, I was only thinking about resolving the ambiguity with array > keys. It's too bad if the parser implementation considerations take > precedence over the purity of the language >
I don't agree that this has anything to do with "purity". If JS didn't have => syntax, why would "fn is a shorter keyword than function" not be a good enough reason to go with this syntax? I think it's equally valid to say that it would be a shame for one syntax shortcut to take precedence over the consistency and maintainability of everything else in the language. Is it really that important to save two key strokes per closure?
> Would that solve the parser problem? BC-wise, I don't think this would be > much of a problem: I have yet to see array keys enclosed with parentheses > in PHP codebases. >
A quick regex search in a code base I had to hand found a few instances of casts, like [(string)$foo => $bar], but indeed no instances of bracketed variables. However, it would feel rather bizarre to be able to write this: [ $x+1 => $foo ] But not this: [ ($x+1) => $foo ] Which I think would have to be the implication for this to make the parsing any easier. On Thu, 14 Mar 2019 at 15:38, David Rodrigues proweb@gmail.com> wrote:
> maybe using [] instead of ()? For instance: "[$x] => $x + 1". PHP don't supports and array as key, so maybe it will not causes any conflict.
Again, I think this solves the ambiguity but not the parsing, although I could be wrong. Consider parsing these three expressions: [ [ $foo ] ] # Nested arrays [ [ $foo => $bar ] ] # Nested arrays with an explicit key [ [ $foo ] => $bar ] # An array containing a closure Regards, -- Rowan Collins [IMSoP]
  104720
March 14, 2019 17:19 joshdifabio@gmail.com (Josh Di Fabio)
On Thu, Mar 14, 2019 at 3:49 PM Rowan Collins collins@gmail.com> wrote:
> > Is it really that important to save two key strokes per closure? >
I'd say that the (probably overwhelming) majority of arrow functions have a single parameter and, in those cases, the JS syntax saves four characters, ignoring whitespace. Another way of looking at it is that you have six characters of boilerplate with the fn() syntax versus two in JS (ignoring whitespace) for single param arrow functions.
  104721
March 14, 2019 17:25 george.banyard@gmail.com ("G. P. B.")
On Thu, 14 Mar 2019 at 18:20, Josh Di Fabio <joshdifabio@gmail.com> wrote:

> On Thu, Mar 14, 2019 at 3:49 PM Rowan Collins collins@gmail.com> > wrote: > > > > Is it really that important to save two key strokes per closure? > > > > I'd say that the (probably overwhelming) majority of arrow functions > have a single parameter and, in those cases, the JS syntax saves four > characters, ignoring whitespace. Another way of looking at it is that > you have six characters of boilerplate with the fn() syntax versus two > in JS (ignoring whitespace) for single param arrow functions. >
No offense but at the end of the day having readable code is better than shorter code IMHO, so I don't really see the problem with having a couple of extra character/keystrokes as this is more readable then the massive boilerplate we currently have. However, I can see people beeing fond of the concise syntax of JS Best regards George P. Banyard