> -----Original Message-----
> From: Hannes Magnusson [mailto:hannes.magnusson@gmail.com]
> Sent: 29 August 2012 22:50
> To: Derick Rethans
> Cc: Nikita Popov; Jared Williams; PHP internals
> Subject: Re: [PHP-DEV] [VOTE] Generators
>
> On Wed, Aug 29, 2012 at 10:19 PM, Derick Rethans
> <derick@php.net> wrote:
> > On Wed, 29 Aug 2012, Nikita Popov wrote:
> >
> >> On Wed, Aug 29, 2012 at 10:10 PM, Derick Rethans
> <derick@php.net> wrote:
> >> > On Wed, 29 Aug 2012, Nikita Popov wrote:
> >> >
> >> >> > function &bind(array $keys, array &$row) {
> >> >> > foreach($keys as $key)
> >> >> > yield $key => $row[$key]; }
> >> >> >
> >> >> > $row = [];
> >> >> > $it = bind(['a', 'b'], $row);
> >> >> >
> >> >> > foreach($it as $key => &$ref)
> >> >> > echo $key;
> >> >> > echo "\n";
> >> >> > foreach($it as $key => &$ref)
> >> >> > echo $key;
> >> >>
> >> >> Thanks, this is now fixed. It'll throw an exception now,
saying
> >> >> that you can't traverse an already closed generator.
> >> >
> >> > Nothing in the core throws an exception, why would this?!
> >>
> >> To my knowledge all iterator-related functionality is supposed to
> >> throw exceptions (as it is a feature related to the object
> oriented
> >> part of PHP). At leas this is what a quick search of the code
base
> >> gave me. (See
> >> http://lxr.php.net/xref/PHP_TRUNK/ext/spl/spl_dllist.c#1248
> >> for example).
> >
> > "ext/spl" - SPL is not *core* language. The generators are. Don't
> > throw exceptions from core features!
>
> In general I agree with core language features shouldn't be
> throwing exceptions...
> But SPL definitely should never have been its own extension
> and most of it should have been core language features - and
> throwing exceptions in many of those cases makes perfect sense.
>
> We also have the case of IteratorAggregate throwing exception
> (which is a *core* language feature, not defined in ext/spl):
>
> $ ./sapi/cli/php -r 'class foo implements IteratorAggregate {
function
> getIterator() { return new stdclass; } } foreach(new foo as $bar)
{}'
>
> Fatal error: Uncaught exception 'Exception' with message
> 'Objects returned by foo::getIterator() must be traversable
> or implement interface Iterator' in Command line code:1 Stack trace:
> #0 Command line code(1): unknown()
> #1 {main}
> thrown in Command line code on line 1
>
Speaking of IteratorAggregates and spl.
I think there should be some discussion about what can be done to get
the spl iterators to handle references.
For instance, you cannot use CachingIterator on a reference yielding
generator.
And think the only method you can get it to work, feels rather kludgy.
class CachingGeneratorIterator implements IteratorAggregate
{
private $it;
function __construct(Generator $it)
{
$this->it = $it;
}
function &getIterator()
{
$previousKey = null;
foreach($this->it as $key => &$ref) {
if ($previousKey !== null)
yield $previousKey => $previousRef;
$previousKey = $key;
$previousRef = &$ref;
}
if ($previousKey !== null)
yield $previousKey => $previousRef;
}
function hasNext() { return $this->it->valid(); }
}
Limitations are that you have to use foreach() rather than current()
to retrieve yielded references, because you can't implement an
iterator with a method signature of ¤t().
Jared