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

Reply via email to