Re: Support rewinding of generators
| From: | Judah Wright | Date: | Wed, 26 Feb 2020 14:41:03 +0000 |
| Subject: | Re: Support rewinding of generators | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108768@lists.php.net to get a copy of this message | ||
Perhaps an easy userland implementation could be type-hinting a new generator type, to indicate that the generator should be rewindable by simply re-calling the function?
// Safe to rewind
function fooRange(int $from, int $to): RewindableGenerator {
for ($i = $from; $i <= $to; $i++) {
yield $i;
}
}
That should be safe to re-call again, but my concern is with generators that modify some external state that should not be called twice. In these cases having a fatal error is a handy feature to prevent re-iterating over things that might cause issues.
~Judah
On Wed, Feb 26, 2020 at 12:47 pm, Nikita Popov <nikita.ppv@gmail.com> wrote:
Hi internals,
Generators currently do not support rewinding -- or rather, only support it
if the generator is at/before the first yield, in which case rewinding is a
no-op.
Generators make it real breeze to implement primitives like
function map(callable $function, iterable $iterable): \Iterator {
foreach ($iterable as $key => $value) {
yield $key => $function($value);
}
}
without having to do through the whole Iterator boilerplate. However, if
you do this, you end up with an iterator that is not rewindable. If you
want to make map() rewindable, you need to go back to a manual Iterator
implementation. As iterators in PHP are assumed to be rewindable by
default, this is somewhat annoying.
There is a relatively simple (at least conceptually) way to make generators
rewindable: Remember the original arguments of the function, and basically
"re-invoke" it on rewind().
I'm wondering what people think about adding this functionality. I think
the main argument against it is that not all generators may behave sensibly
if you re-run their code -- there's probably a reasonable expectation that
an iterator will return the same sequence of values are rewinding,
something which we cannot guarantee with generators, but also don't enforce
with normal iterators either.
Regards,
Nikita