Re: [RFC] Arrow functions / short closures

This is only part of a thread. view whole thread
  104710
March 14, 2019 09:26 nikita.ppv@gmail.com (Nikita Popov)
On Wed, Mar 13, 2019 at 4:56 PM Nikita Popov ppv@gmail.com> wrote:

> Hi internals, > > 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 > > This is based on a previous (withdrawn) proposal by Levi & Bob. It uses > the syntax > > fn($x) => $x * $multiplier > > and implicit by-value variable binding. This example is roughly equivalent > to: > > function($x) use($multiplier) { return $x * $multiplier; } > > The RFC contains a detailed discussion of syntax choices and binding modes. >
Trying to reply to everyone in one mail... 1. Using f() =>. This is possible. However, f would become a reserved keyword, and I'm very leery of making a single-character reserved keyword. Additionally I think that the fn() => syntax is more intuitive, but maybe that's my Rust influences speaking ;) 2. $this binding. Yes, $this is indeed bound exactly as with normal closures. I've explicitly mentioned this in the RFC now. 3. yield. Using yield is per-se not a problem. You can write `() => yield 42`, which is basically `function() { return yield 42; }`, which is okay, because yield is an expression and generators can return values since PHP 7. It also doesn't seem particularly useful though, as you're limited to yielding a single value. However, in the current form short closures are a replacement for list comprehensions only insofar they make the use of map() and filter() non-torturous. You couldn't actually use them to get a comprehension-like syntax as suggested in the other thread: $gen = (fn() => foreach ($list as $elem) yield $elem * 2))(); // would be, hypothetically: $gen = (function() use($list) { return foreach ($list as $elem) yield $elem * 2; }))(); The yield part here isn't the problem, "return foreach" is. Unlike yield, foreach is a statement, not an expression. To make this work we'd need a block form of short closures: $gen = (fn() { foreach ($list as $elem) yield $elem * 2; })(); // or maybe $gen = (fn() => { foreach ($list as $elem) yield $elem * 2; })(); Either way, I wouldn't want to read that code ;) The right way to write this is $list->map(fn($elem) => $elem * 2). 4. ($x) => $x instead of $x => $x. As Rowan mentioned, this doesn't really change things. Where $x is valid, ($x) is in most cases also valid. Regards, Nikita