php - When does the NoRewindIterator rewind the inner Iterator? -


by name clear when php's norewinditerator rewinds: never.

but sometimes, esp. when extending it, ask myself: ever rewind? rewind once? if need it, need implement (first) rewind traversable might require it?

i wonder inner iterator here, iterator norewinditerator class takes parameter constructor.

for example:

$iterator = new someiterator(); // implements iterator $norewind = new norewinditerator($iterator); foreach ($norewind $value) {     break; } 

will $iterator->rewind() never called when using $norewind here on? or called once first time $norewind->rewind() invoked (e.g. within first foreach in example). or maybe on construct?

like name of class alone (norewinditerator), the manual has following wording in specific:

norewinditerator - iterator cannot rewound.

and concrete method:

norewinditerator::rewind() - prevents rewind operation on inner iterator.

this implies iterator::rewind() method not passed through inner iterator. tests show this, here simple 1 i've been running (code of iterators not part of php in iterator garden):

$iterator = new rangeiterator(1, 1); $debug    = new debugiteratordecorator($iterator); $norewind = new norewinditerator($debug);  echo "first foreach:\n";  foreach ($norewind $value) {     echo "iteration value: $value\n"; } 

in code, debug-iterator prints (echoes) iteration information on fly:

first foreach: iterating (rangeiterator): #0 valid() iterating (rangeiterator): #0 parent::valid() true iterating (rangeiterator): #0 current() iterating (rangeiterator): #0 parent::current() 1 iteration value: 1 iterating (rangeiterator): #1 next() iterating (rangeiterator): #1 after parent::next() iterating (rangeiterator): #1 valid() iterating (rangeiterator): #1 parent::valid() false 

as shows, $iterator->rewind() never called.

this makes sense same reasons given in related question: why must rewind iteratoriterator. norewinditerator extends iteratoriterator , different it's parent class, getinneriterator() method returns iterator , not traversable.

this change allows initialize rewind when need to:

echo "\n\$calling norewind->getinneriterator()->rewind():\n";  $norewind->getinneriterator()->rewind();  echo "\nsecond foreach:\n";  foreach ($norewind $value) {     echo "iteration value: $value\n"; } 

exemplary debug output again:

$calling norewind->getinneriterator()->rewind(): iterating (rangeiterator): #0 rewind() iterating (rangeiterator): #0 after parent::rewind()  second foreach: iterating (rangeiterator): #0 valid() iterating (rangeiterator): #0 parent::valid() true iterating (rangeiterator): #0 current() iterating (rangeiterator): #0 parent::current() 1 iteration value: 1 iterating (rangeiterator): #1 next() iterating (rangeiterator): #1 after parent::next() iterating (rangeiterator): #1 valid() iterating (rangeiterator): #1 parent::valid() false 

knowing these details allow create onetimerewinditerator example:

/**  * class onetimerewinditerator  */ class onetimerewinditerator extends norewinditerator {     private $didrewind = false;      public function rewind() {         if ($this->didrewind) return;          $this->didrewind = true;         $this->getinneriterator()->rewind();     } } 

Comments

Popular posts from this blog

python - How to create a legend for 3D bar in matplotlib? -

java - Multi-Label Document Classification -

php - Dynamic url re-writing using htaccess -