On Thu, 21 Mar 2019 at 11:00, Robert Hickman <robehick...@gmail.com> wrote:

> I was only making a point for where a non-generator version of
> comprehensions could be useful, under the premise "Therefore, a
> lazy-evaluating syntax is more powerful, in that it can do everything
> an eager-evaluating one can do *and more*.". This implies that it
> dosn't have any downsides, whereas performance may be a downside.
>


Ah, OK, I see where you're coming from. I'm no expert, but I'm not sure how
much difference it would actually make.

Whether the comprehension is eagerly evaluated internally, or by a call to
iterator_to_array, the input will always need to looped over exactly once,
with each element being tested against the condition and run through the
output mapping.

A manual eager implementation (with no output mapping, for simplicity)
would look like this:

foreach ( $array as $element ) {
    if ( someCondition ) $newArray[] = $element;
}

Which is basically equivalent to this:

while ( $element = $arrayIterator->next() ) {
    if ( someCondition ) $newArray[] = $element;
}

A lazy implementation just moves the if check into the iterator; it might
look like this:

while ( $element = $filteredArrayIterator->next() ) {
    if ( someCondition ) $newArray[] = $element;
}

But  $filteredArrayIterator->next() is actually $arrayIterator->next() with
a built-in if check, so you could also picture it as doing this:

while ( $element = $arrayIterator->nextIf ( someCondition ) ) {
    $newArray[] = $element;
}

So the underlying operations are the same, they just happen in different
orders.


The only real difference I can see is that under a very specific set of
circumstances, it could be compiled into a tight loop on the CPU. It would
require a JIT to check all of the following held, though:

- The input is a plain array, not any other iterable
- The condition can be inlined (e.g. not a function call like "if (
checkSomething($x) )")
- The output mapping can be inlined (e.g. not a function call like "yield
doSomething($x)")

Returning a generator by default just requires an extra check in that list:

- The expression is contained within iterator_to_array (or whatever syntax
shortcut we come up with for that).


I might be wrong, though, in which case this would indeed be an argument in
favour of having a dedicated array-returning syntax, either alongside or
instead of a generator-returning one.


Regards,
-- 
Rowan Collins
[IMSoP]

Reply via email to