On Tue, Apr 9, 2019, at 3:31 AM, Stephen Reay wrote: > > > > On 5 Apr 2019, at 21:29, Larry Garfield <la...@garfieldtech.com> wrote: > > > > On Thu, Apr 4, 2019, at 10:46 PM, Stephen Reay wrote: > > > >>> Discussion: > >>> > >>> For me, the inability to work with arrays is the big problem with the > >>> second approach. I very very often am type declaring my returns and > >>> parameters as `iterable`, which means I may have an array and not know > >>> it. Using approach 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, though, I'm pretty sure is out of scope. > >>> > >>> Frankly were it not for that limitation I'd say I favor the chained > >>> method style, as while it is more verbose it is also more > >>> self-documenting. Given that limitation, I'm torn but would probably > >>> lean toward option 1. And of course there's the "methods that apply to > >>> all traversable objects" thing which is its own can of worms I know > >>> nothing about. > >>> > >>> (If someone has a suggestion for how to resolve that disadvantage, I'd > >>> love to hear it.) > >>> > >>> Those seem like the potential options. Any further thoughts? Or > >>> volunteers? :-) > >>> > >>> --Larry Garfield > >>> > >>> -- > >>> PHP Internals - PHP Runtime Development Mailing List > >>> To unsubscribe, visit: http://www.php.net/unsub.php > >>> > >> > >> (Sorry, sent from wrong address, sending again!) > >> > >> Hi Larry, > >> > >> I’ve mostly ignored this thread until now - I find a lot of the > >> “shorter syntax” (i.e. the short closures RFC) to sound a lot like the > >> arguments “I don’t like semicolons/it has to be ‘pretty'” that happen > >> in other language communities. > > > > In defense of terse syntax, it's not a question of "pretty". It's a > > question of making it feasible to operate at a higher level of abstraction. > > Really, generators didn't offer much of anything that couldn't be done by > > defining and building an Iterator-implementing class. They're "just" > > syntactic sugar. However, they allow the developer to conceptualize a > > problem in a different way, and most of the machinery then falls away. > > That means I can now think in terms of "call this function, then iterate > > the stream it gives me back" and within the function I can just have normal > > logic with `yield` floating around as needed. Anything I do there *could* > > be done with an Iterator class; 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 think about the problem, and in a very > > good way. > > > > Similarly, short closures isn't about "let's make functions easier to > > write". That's a side effect. They should be thought of more as a way to > > easily encapsulate "apply this expression to this set of values". So the > > advantage is not that > > > > $y= 5; > > array_map(fn($x) => $x*$y, $arr); > > > > is less typing than > > > > array_map(function ($x) use ($y) { > > return $x * $y; > > }); > > > > It's that in the first option you don't think about it as a function, you > > think about it as an expression applied over a set. That's a higher-order > > mental operation, and once you start doing that you can conceptualize the > > program in a different, more higher-order, less bug-prone way. > > > > 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 > > everything" rather than think in terms of the machinery of iteration. > > > > I see comprehensions the same way. At one level they're "just" short > > syntax for generators, but they're more about making it possible to reason > > about your logic at a higher level, in a more declarative fashion. > > > > (There's probably a conference talk in there somewhere, from for to foreach > > to iterators to generators to comprehensions, each coming up one level of > > abstraction.) > > > >> But the first example you give here, I can see the logical approach - > >> as you say, it’s a currently-valid foreach statement, wrapped in square > >> brackets. Would it have to be a single line to parse, or could it be > >> wrapped when the condition gets longer (yes I know it could just become > >> a regular generator then, I’m just wondering about what happens when > >> someone adds a new line in there (in a language that historically > >> doesn’t care about newlines) > > > > 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 > > take a different approach. (A defined function with real foreach > > statements, multiple defined comprehensions that reference each other, etc.) > > > >> I like the second concept a lot too, but how would this cope with for > >> example: a userland class implements iterator but *also* defines a > >> `filter(callback $fn): self` method for the exact same purposes were > >> discussing. How is that handled? > > > > I have no idea at the moment. :-) That would be a possible BC issue. My > > first thought is that if an iterator defines filter(), map(), etc. itself > > then 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 push it to PHP 8, which would be unfortunate but if that's the > > way it goes, that's the way it goes.) > > > >> On Fri, Apr 5, 2019, at 3:41 AM, Michał Brzuchalski wrote: > >> Hi Larry, > >> > >> pt., 5 kwi 2019 o 03:55 Larry Garfield <la...@garfieldtech.com> napisał(a): > >> > >>> > >>> Advantages: > >>> > >>> * 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). > >>> > >> > >> IMO not nicely cause spread operator in current proposal raises an error on > >> key preserved traversable[1]. > >> This means example like below would fail > >> > >> $a = ['foo' => true, ...[foreach($_GET as $key => $value) yield $key => > >> $value]]; // error > >> > >> [1] https://wiki.php.net/rfc/spread_operator_for_array#string_keys > > > > True; it's not a complete solution. Per the thread on spread string keys > > may make a comeback. But I was thinking more of a case of: > > > > $arr = ...[foreach ($list as $k => $v) yield $k => $v]; > > > > For those cases where you really do want an array to operate on next, > > rather than a generator. If you're in a situation where ... doesn't work, > > iterator_to_array() still does; it's just more verbose. > > > > --Larry Garfield > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: http://www.php.net/unsub.php > > > > Hi Larry, > > Sorry I haven’t replied before now. > > I understand that there is an actual tangible benefit being pursued > here - but so many of the comments seem to be focussed around removing > every possible character due to some weird belief that less characters > is automatically “better”, and it always reminds of the “I don’t like > semicolons they're ugly” type comments that always come up in JS > communities. > > Best of luck! > > > Cheers > > Stephen
Um. Isn't that what you just said above, in the email I replied to at length? Like, it's in the quoted text above... --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php