tags:

views:

46

answers:

2
$arrayIter = new ArrayIterator( array(1, 2) );
$iterIter = new IteratorIterator($arrayIter);

var_dump($iterIter->valid()); //false
var_dump($arrayIter->valid()); //true

If I first call $iterIter->rewind(), then $iterIter->valid() is true. I'm curious why it requires that rewind() be called. I imagine there's good reason for it, but I would have expected it to simply start iteration at whatever state it's inner iterator is in, and leave it as an option to rewind before beginning iteration.

calling next() also seems to put it in a "valid" state(although it advances to the next position, suggesting it was previously at the first position).

$arrayIter = new ArrayIterator(array(1,2));
$iterIter = new IteratorIterator($arrayIter);

$iterIter->next();
var_dump($iterIter->valid()); 

Again, I'm curious why I need to call rewind(), despite the inner iterator being in a valid state.

+3  A: 

With a fresh iterator the position isn't initialized, simply for performance reason, you can stack iterators on top of other iterators, if all of them would rewind during construction there would be some performance impact, additionally some iterators might change their first value after the constructor was executed - which is unknown to iterators further out.

Iterators are usually executed by foreach() which does a rewind() first ...

johannes
I suspected something like this. I already figured an auto-rewind would be undesirable, but couldn't understand why rewind was required. Could you point an example of an iterator that changes its first value?
chris
Simple example: $ai = new AppendIterator(); $ii = new IteratorIterator($ai); $ai->append(new ArrayIterator(array(1,2,3));
johannes
In the previous small example: Doing a rewind during creation of $ai is useless, as there are no values. During creation of $ii would have no effect (except wasted CPU cycles) either. during append()would be wrong as one might append iterators during the iteration.
johannes
Ok. I wasn't aware that the values from the inner iterator were cached into the outer iterator. It seems like the values are retrieved both when rewind() and next() are called. I thought the values would be retrieved from the inner iterator when current() is called. I had previously looked at this, which lead me astray http://www.php.net/~helly/php/ext/spl/iteratoriterator_8inc-source.html
chris
A: 

Like @johannes said, the position isn't initialized in the IteratorIterator and thus it is not valid before any other of it's methods are run on it or it is used with foreach()

Try to do

var_dump( $iterIter->current() ); // NULL
var_dump( $iterIter->getInnerIterator()->current() ); // 1

And also

$iterIter->rewind();
var_dump( $iterIter->current() ); // 1
var_dump( $iterIter->getInnerIterator()->->current() );  // 1

And also note that on an unitiliazed IteratorIterator:

$iterIter->next(); // 2
var_dump( $iterIter->current()) ; // 2 (from NULL to 2)
var_dump( $iterIter->getInnerIterator()->current() );  // 2

Note that $arrayIter from your code snippet is identical to $iterIter->getInnerIterator().

Hope that shed some light.

Gordon