Re: Fixing strange foreach behavior.
| From: | Rowan Collins | Date: | Fri, 16 Jan 2015 16:22:05 +0000 |
| Subject: | Re: Fixing strange foreach behavior. | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-80648@lists.php.net to get a copy of this message | ||
Yasuo Ohgaki wrote on 16/01/2015 08:40:
Hi all, Take a look at http://3v4l.org/HbVnd foreach should not affect internal(zval) array position, but it does. I'm not sure why foreach works this way, but HHVM behavior is reasonable. IMHO. PHP 7 would be perfect opportunity fix this behavior. Any comments?I seem to remember somebody mentioning that the pointer is reused in some situations and not others. I think the reason is efficiency - we have a pointer associated with each array, which is rarely used, so why not borrow it for foreach? (Answer: because it causes the oddity you just spotted. :P) For instance, if you put a reset() in the middle of the foreach loop, it doesn't interrupt the progress of the loop, but does cause it to be tracked separately and output "Apple" after the loop finishes: http://3v4l.org/KTCrI There are other weird cases, like nesting two foreach loops over the same variable: - with a true array, the loops are independent (both loops see the full set of values): http://3v4l.org/lJTQG - with a rewindable Traversable, such as SimpleXMLElement, they interact (the inner loop sees all values, but the outer loop doesn't continue after the inner one completes): http://3v4l.org/fs2Jv - with a non-rewindable Traversable, such as a Generator, PHP tries to rewind and gives a fatal error, while HHVM simply uses up the last values of the generator on the inner loop (possibly a bug?): http://3v4l.org/BYOmQ My conclusion: don't try and nest foreach or any related constructs using the same variable, because the behaviour is not guaranteed to be in any way sane. Regards, -- Rowan Collins [IMSoP]