Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:88594 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 78691 invoked from network); 1 Oct 2015 07:07:49 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Oct 2015 07:07:49 -0000 Authentication-Results: pb1.pair.com header.from=bjorn.x.larsson@telia.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=bjorn.x.larsson@telia.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain telia.com from 81.236.60.154 cause and error) X-PHP-List-Original-Sender: bjorn.x.larsson@telia.com X-Host-Fingerprint: 81.236.60.154 v-smtpout1.han.skanova.net Received: from [81.236.60.154] ([81.236.60.154:56566] helo=v-smtpout1.han.skanova.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 30/71-04700-0CBDC065 for ; Thu, 01 Oct 2015 03:07:45 -0400 Received: from [192.168.7.4] ([195.198.188.252]) by cmsmtp with SMTP id hXxsZnTo79HQVhXxtZ082D; Thu, 01 Oct 2015 09:07:41 +0200 To: =?UTF-8?Q?Pavel_Kou=c5=99il?= , Levi Morrison References: Cc: PHP internals Message-ID: <560CDBBF.9090407@telia.com> Date: Thu, 1 Oct 2015 09:07:43 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4wfK/71kQlZneaqFWb9RS0IjQ6obAYnW559BExyYZLKC9PNeAkd8NDeEa234Ieiasi1o7sU86S7lPK1z2s4Kpav7z9tiKeGnc8tcxOASxU7Rkd+9Q+vfG9YoCGuVJn0Y3744yqG/qzfjoBJb5M+zKLa5VTpdkHl/MqmJNZncqd5riIrlMUvQCS3yIzvi1fC4IFHXcCyw+vpqUTCe1djjLgN1V9Ky7AfWMXrlgT6h+03vYHAlIHXZcmA3Z4Ng/yXpv/Nw== Subject: Re: [PHP-DEV] Arrow function expressions in PHP From: bjorn.x.larsson@telia.com (=?UTF-8?Q?Bj=c3=b6rn_Larsson?=) Den 2015-09-28 kl. 23:38, skrev Pavel Kouřil: > On Sat, Sep 26, 2015 at 6:17 PM, Levi Morrison wrote: >> (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", >> "Beryl­lium" >> ]; >> >> 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 >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> > > Hello, > > personally, as a purely userland dev, I feel that the correct syntax > would be the "simplest" one - and that's imho the (Type &$x) ==> expr > > Or the version with ~> operator - I don't care which one gets in, > althought I would rather see the ==> one. :) > > I understand that there might be some ambiguity in the parser that > would need to be solved by backtracking, but for using the language, > the "simplest" option should IMHO be the correct one. Also not > introducing any more "stuff" (like new parameter types syntax) would > be a plus. > > For the need to have a single parameter enclosed with ( ) - by > thinking more and more about it, I think that having the one special > case for not requiring parenthesis around parameters is pretty uselss, > since it would have to be there anyways if you wrote the typehint. > > PS: the [fn($x) => $x * 2] seems ambigous, from reader's POV; key of > the item is result of fn($x) and value is $x * 2? Also, it would be a > huge BC break with not allowing you to name functions fn(), wouldn't > it? > > -- > Regards > Pavel Kouřil > Being a userland developer myself I totally agree! Keeping it simple, consistent & unambiguous. Regards //Björn Larsson