Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:105160 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 64085 invoked from network); 9 Apr 2019 11:34:50 -0000 Received: from unknown (HELO mail1.25mail.st) (206.123.115.54) by pb1.pair.com with SMTP; 9 Apr 2019 11:34:50 -0000 Received: from [10.176.223.22] (ppp-27-55-172-208.revip3.asianet.co.th [27.55.172.208]) by mail1.25mail.st (Postfix) with ESMTPSA id 0F32860378; Tue, 9 Apr 2019 08:31:35 +0000 (UTC) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (1.0) X-Mailer: iPhone Mail (16E227) In-Reply-To: <03b2e206-750f-4afb-806b-65ff77eb6893@www.fastmail.com> Date: Tue, 9 Apr 2019 15:31:31 +0700 Cc: internals@lists.php.net Content-Transfer-Encoding: quoted-printable Message-ID: References: <6d3be21f-d63a-3fc6-94ee-0bde8e313d66@xs4all.nl> <37bb451f-a1b2-4c69-91e2-f2ab6c4798e7@www.fastmail.com> <76D63EA5-7F6D-43E6-ACC2-E55B5816BEF5@koalephant.com> <03b2e206-750f-4afb-806b-65ff77eb6893@www.fastmail.com> To: Larry Garfield Subject: Re: [PHP-DEV] RFC Draft: Comprehensions From: php-lists@koalephant.com (Stephen Reay) > On 5 Apr 2019, at 21:29, Larry Garfield wrote: >=20 > On Thu, Apr 4, 2019, at 10:46 PM, Stephen Reay wrote: >=20 >>> Discussion: >>>=20 >>> For me, the inability to work with arrays is the big problem with the se= cond approach. I very very often am type declaring my returns and parameter= s as `iterable`, which means I may have an array and not know it. Using appr= oach 2 means I suddenly really really need to care which kind of iterable it= is, which defeats the purpose of `iterable`. Calling methods on arrays, th= ough, I'm pretty sure is out of scope. >>>=20 >>> Frankly were it not for that limitation I'd say I favor the chained meth= od style, as while it is more verbose it is also more self-documenting. Giv= en that limitation, I'm torn but would probably lean toward option 1. And o= f course there's the "methods that apply to all traversable objects" thing w= hich is its own can of worms I know nothing about. >>>=20 >>> (If someone has a suggestion for how to resolve that disadvantage, I'd l= ove to hear it.) >>>=20 >>> Those seem like the potential options. Any further thoughts? Or volunt= eers? :-) >>>=20 >>> --Larry Garfield >>>=20 >>> --=20 >>> PHP Internals - PHP Runtime Development Mailing List >>> To unsubscribe, visit: http://www.php.net/unsub.php >>>=20 >>=20 >> (Sorry, sent from wrong address, sending again!) >>=20 >> Hi Larry, >>=20 >> I=E2=80=99ve mostly ignored this thread until now - I find a lot of the=20= >> =E2=80=9Cshorter syntax=E2=80=9D (i.e. the short closures RFC) to sound a= lot like the=20 >> arguments =E2=80=9CI don=E2=80=99t like semicolons/it has to be =E2=80=98= pretty'=E2=80=9D that happen=20 >> in other language communities. >=20 > In defense of terse syntax, it's not a question of "pretty". It's a quest= ion of making it feasible to operate at a higher level of abstraction. Real= ly, generators didn't offer much of anything that couldn't be done by defini= ng and building an Iterator-implementing class. They're "just" syntactic su= gar. However, they allow the developer to conceptualize a problem in a diff= erent way, and most of the machinery then falls away. That means I can now t= hink in terms of "call this function, then iterate the stream it gives me ba= ck" and within the function I can just have normal logic with `yield` floati= ng around as needed. Anything I do there *could* be done with an Iterator c= lass; I've done it some weird things with Iterators before. But the ability= to think in terms of an ad-hoc stream of values really changes the way you t= hink about the problem, and in a very good way. >=20 > Similarly, short closures isn't about "let's make functions easier to writ= e". That's a side effect. They should be thought of more as a way to easil= y encapsulate "apply this expression to this set of values". So the advanta= ge is not that >=20 > $y=3D 5; > array_map(fn($x) =3D> $x*$y, $arr); >=20 > is less typing than >=20 > array_map(function ($x) use ($y) { > return $x * $y; > }); >=20 > It's that in the first option you don't think about it as a function, you t= hink about it as an expression applied over a set. That's a higher-order me= ntal operation, and once you start doing that you can conceptualize the prog= ram in a different, more higher-order, less bug-prone way. >=20 > Just like there's nothing you can do with foreach() that you can't also do= with for()... but foreach() lets you think in terms of "just do it to every= thing" rather than think in terms of the machinery of iteration. >=20 > I see comprehensions the same way. At one level they're "just" short synt= ax for generators, but they're more about making it possible to reason about= your logic at a higher level, in a more declarative fashion. >=20 > (There's probably a conference talk in there somewhere, from for to foreac= h to iterators to generators to comprehensions, each coming up one level of a= bstraction.) >=20 >> But the first example you give here, I can see the logical approach -=20 >> as you say, it=E2=80=99s a currently-valid foreach statement, wrapped in s= quare=20 >> brackets. Would it have to be a single line to parse, or could it be=20 >> wrapped when the condition gets longer (yes I know it could just become=20= >> a regular generator then, I=E2=80=99m just wondering about what happens w= hen=20 >> someone adds a new line in there (in a language that historically=20 >> doesn=E2=80=99t care about newlines) >=20 > The RFC specifically says whitespace is irrelevant. If you want to break a= comprehension across multiple lines, you do you. But if it's getting large= enough that it's ugly to read that way it's a good sign you may want to tak= e a different approach. (A defined function with real foreach statements, m= ultiple defined comprehensions that reference each other, etc.) >=20 >> I like the second concept a lot too, but how would this cope with for=20 >> example: a userland class implements iterator but *also* defines a=20 >> `filter(callback $fn): self` method for the exact same purposes were=20 >> discussing. How is that handled? >=20 > I have no idea at the moment. :-) That would be a possible BC issue. My f= irst thought is that if an iterator defines filter(), map(), etc. itself the= n it's overriding the default behavior and can do what it wants, but there's= also possible function signature mismatches there. It may just have to be a= BC break in those cases. I am open to alternate suggestions. (That may pus= h it to PHP 8, which would be unfortunate but if that's the way it goes, tha= t's the way it goes.) >=20 >> On Fri, Apr 5, 2019, at 3:41 AM, Micha=C5=82 Brzuchalski wrote: >> Hi Larry, >>=20 >> pt., 5 kwi 2019 o 03:55 Larry Garfield napisa=C5= =82(a): >>=20 >>>=20 >>> Advantages: >>>=20 >>> * Very compact. >>> * Works for both arrays and traversables >>> * Would play very nicely with the proposed spread operator for iterables= ( >>> https://wiki.php.net/rfc/spread_operator_for_array). >>>=20 >>=20 >> IMO not nicely cause spread operator in current proposal raises an error o= n >> key preserved traversable[1]. >> This means example like below would fail >>=20 >> $a =3D ['foo' =3D> true, ...[foreach($_GET as $key =3D> $value) yield $ke= y =3D> >> $value]]; // error >>=20 >> [1] https://wiki.php.net/rfc/spread_operator_for_array#string_keys >=20 > True; it's not a complete solution. Per the thread on spread string keys m= ay make a comeback. But I was thinking more of a case of: >=20 > $arr =3D ...[foreach ($list as $k =3D> $v) yield $k =3D> $v]; >=20 > For those cases where you really do want an array to operate on next, rath= er than a generator. If you're in a situation where ... doesn't work, itera= tor_to_array() still does; it's just more verbose. >=20 > --Larry Garfield >=20 > --=20 > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >=20 Hi Larry, Sorry I haven=E2=80=99t replied before now. I understand that there is an actual tangible benefit being pursued here - b= ut so many of the comments seem to be focussed around removing every possibl= e character due to some weird belief that less characters is automatically =E2= =80=9Cbetter=E2=80=9D, and it always reminds of the =E2=80=9CI don=E2=80=99t= like semicolons they're ugly=E2=80=9D type comments that always come up in J= S communities. Best of luck! Cheers Stephen=20=