Bug #63823 [Opn]: SPL InfiniteIterator needs explicit rewind to be usable in a closure
| From: | laruence@php.net | Date: | Fri, 21 Dec 2012 02:35:41 +0000 |
| Subject: | Bug #63823 [Opn]: SPL InfiniteIterator needs explicit rewind to be usable in a closure | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-175516@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=63823&edit=1
ID: 63823
Updated by: laruence@php.net
Reported by: sixd@php.net
Summary: SPL InfiniteIterator needs explicit rewind to be
usable in a closure
Status: Open
Type: Bug
Package: SPL related
Operating System: Linux
PHP Version: 5.4Git-2012-12-21 (Git)
Block user comment: N
Private report: N
New Comment:
I saw similar report before, and remembered someone mark it as won't fix.. I just
can not find the previous report now...
Previous Comments:
------------------------------------------------------------------------
[2012-12-21 02:20:57] sixd@php.net
A bigger example is:
<?php
echo "'foreach' on ArrayIterator\n";
$c = array('one', 'two', 'three');
$c_it = new ArrayIterator($c);
foreach ($c_it as $key => $val) {
var_dump($val);
}
echo "\n'foreach' on InfiniteIterator\n";
$a = array('one', 'two', 'three');
$a_it = new InfiniteIterator(new ArrayIterator($a));
$i = 0;
foreach ($a_it as $key => $val) {
if ($i++ >= 7) break;
var_dump($val);
}
echo "\n'for' on ArrayIterator\n";
$d = array('one', 'two', 'three');
$d_it = new ArrayIterator($d);
for ($i = 0; $i < 3; $i++) {
var_dump($d_it->current());
$d_it->next();
}
echo "\n'for' on InfiniteIterator\n";
$b = array('one', 'two', 'three');
$b_it = new InfiniteIterator(new ArrayIterator($b));
for ($i = 0; $i < 7; $i++) {
var_dump($b_it->current());
$b_it->next();
}
?>
This outputs:
'foreach' on ArrayIterator
string(3) "one"
string(3) "two"
string(5) "three"
'foreach' on InfiniteIterator
string(3) "one"
string(3) "two"
string(5) "three"
string(3) "one"
string(3) "two"
string(5) "three"
string(3) "one"
'for' on ArrayIterator
string(3) "one"
string(3) "two"
string(5) "three"
'for' on InfiniteIterator
NULL
string(3) "two"
string(5) "three"
string(3) "one"
string(3) "two"
string(5) "three"
string(3) "one"
So the odd behavior is with the last loop.
A "real" life script (from discussion on php.internals) is:
<?php
// Replacing words in a string with a sequential, repeating set of replacement words
$replacements = array('one', 'two', 'three');
$replacements_iterator = new InfiniteIterator(new ArrayIterator($replacements));
$replacements_iterator->rewind(); // why is the rewind needed?
$result = preg_replace_callback(
'/word/',
function($matches) use ($replacements_iterator) {
$r = $replacements_iterator->current();
$replacements_iterator->next();
return $r;
},
'word word word word word'
);
var_dump($result);
// Outputs:
// string(21) "one two three one two"
// Without the call to $replacements_iterator->rewind(), the output is:
// string(18) " two three one two"
?>
------------------------------------------------------------------------
[2012-12-21 02:17:17] sixd@php.net
Description:
------------
SPL's InfiniteIterator returns NULL for the first access, unless used in a
'foreach' loop, or a rewind is done.
This means that an explicit rewind is needed before an InfiniteIterator can be
safely be used in an application.
Test script:
---------------
<?php
$b = array('one', 'two', 'three');
$b_it = new InfiniteIterator(new ArrayIterator($b));
for ($i = 0; $i < 7; $i++) {
var_dump($b_it->current());
$b_it->next();
}
?>
Expected result:
----------------
string(3) "one"
string(3) "two"
string(5) "three"
string(3) "one"
string(3) "two"
string(5) "three"
string(3) "one"
Actual result:
--------------
NULL
string(3) "two"
string(5) "three"
string(3) "one"
string(3) "two"
string(5) "three"
string(3) "one"
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=63823&edit=1