Bug #70812 [Nab]: Nested foreach with iterators
| From: | fra dot casula at gmail dot com | Date: | Thu, 29 Oct 2015 17:09:01 +0000 |
| Subject: | Bug #70812 [Nab]: Nested foreach with iterators | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-196882@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=70812&edit=1
ID: 70812
User updated by: fra dot casula at gmail dot com
Reported by: fra dot casula at gmail dot com
Summary: Nested foreach with iterators
Status: Not a bug
Type: Bug
Package: *General Issues
Operating System: Ubuntu 15.10 x64
PHP Version: 5.6.14
Block user comment: N
Private report: N
New Comment:
I get what you're saying, arrays are by value. Objects, starting from PHP5, are by reference.
Still if I unset an element of the same array in the nested foreach I get that element wiped in the
main array as well.
$a = [1, 2, 3, 4];
foreach ($a as $i => $v) {
foreach ($a as $i2 => $v2) {
if ($i2 % 2 == 0) {
unset($a[$i2]);
}
}
}
var_dump($a); // it prints 2, 4 (of course)
If each foreach is working with its own array copy like you said then there's probably a scope
issue?
The whole thing is confusing because someone would think that iterators work just like a normal
array but then, even if we don't implement a thing and use the ready-to-use ArrayIterator
class, we get a completely different behaviour with a simple thing like a nested foreach. It's
not just a completely different behaviour, it's just unreliable. The ArrayIterator class, as it
is, can't even be used in a nested foreach unless we start setting positions manually. That
would probably make us loose the benefit of using iterators in the first instance.
Previous Comments:
------------------------------------------------------------------------
[2015-10-29 15:41:21] bwoebi@php.net
The difference is that arrays are by-value â they have all own copies which are all
individually iterated. [At least that's how they function semantically.]
Iterators though are objects and thus share a common state.
It's not like arrays would be seeking each time and iterators not. Just each foreach works on
its own array copy, but shares the object.
------------------------------------------------------------------------
[2015-10-29 13:49:41] fra dot casula at gmail dot com
Description:
------------
A nested foreach on the same iterator doesn't produce the same result that is produced when
using plain arrays.
The nested foreach should call seek() to reset the internal pointer to its correct position so that
the first foreach can resume where it stopped.
Test script:
---------------
http://pastebin.com/EQrUZ7AQ
Expected result:
----------------
I expect to see the same output for all four cases in the example code. The expected output is:
first loop 0
second loop 0
second loop 1
second loop 2
first loop 1
second loop 0
second loop 1
second loop 2
first loop 2
second loop 0
second loop 1
second loop 2
Actual result:
--------------
first loop 0
second loop 0
second loop 1
second loop 2
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=70812&edit=1