Re: Support rewinding of generators

From: Date: Wed, 26 Feb 2020 15:03:00 +0000
Subject: Re: Support rewinding of generators
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-108769@lists.php.net to get a copy of this message
Hi Nikita, On 26 February 2020 11:47:14 GMT+00:00, Nikita Popov <nikita.ppv@gmail.com> wrote: >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(). This is an interesting idea. There is a gotcha though, neatly demonstrated by your example: >function map(callable $function, iterable $iterable): \Iterator { > foreach ($iterable as $key => $value) { > yield $key => $function($value); > } >} If the $iterable passed in is anything other than an array, re-invoking the function won't actually rewind it. That can be fixed by explicitly rewinding at the start: function map(callable $function, iterable $iterable): \Iterator { reset($iterable); foreach ($iterable as $key => $value) { yield $key => $function($value); } } But now we have a different problem: if we pass an iterator that doesn't support rewinding, we'll get an error immediately. In other cases, the side-effects of running the "constructor" itself might be undesirable. For instance, it might re-run an SQL query, rather than rewinding a cursor: public function getResultsIterator($sql) { $cursor = $this->runQuery($sql); foreach ( $cursor->getNext() as $row ) { yield $this->formatRow($row); } } I think the fix would be to return a generator rather than yielding directly, like this: public function getResultsIterator($sql) { $generator = function($cursor) { $cursor->rewind(); foreach ( $cursor->getNext() as $row ) { yield $this->formatRow($row); } }; $cursor = $this->runQuery($sql); return $generator($cursor); } In general, it feels like it would be useful for generators that knew it was going to happen, but a foot-gun for generators that weren't expecting it, so I like Judah's suggestion of an opt-in mechanism of some sort. Regards, -- Rowan Tommins [IMSoP]

« previous php.internals (#108769) next »