Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:80692 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 63914 invoked from network); 17 Jan 2015 11:43:21 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 17 Jan 2015 11:43:21 -0000 Authentication-Results: pb1.pair.com header.from=rowan.collins@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=rowan.collins@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.215.52 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 209.85.215.52 mail-la0-f52.google.com Received: from [209.85.215.52] ([209.85.215.52:35506] helo=mail-la0-f52.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 5A/D2-47555-6DA4AB45 for ; Sat, 17 Jan 2015 06:43:19 -0500 Received: by mail-la0-f52.google.com with SMTP id hs14so22690003lab.11 for ; Sat, 17 Jan 2015 03:43:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:cc :content-type; bh=IaQnd3Dqo5TRyTSPoAmLosehLXi0CPGwzAOrSsSwx1k=; b=U+tiQWR/9ozERz0MzjpIk/czYamkmwyaFzj/KGR9n83GfvWCQ/SVqaTT39oNWc7t+z P36F/yeOQT6RyDKQZcWVczT8vRlZlrAOaKJjDJEVXTzv4no23D18SC9O6+OAsuu7xnir K3548K1XBHB07FNhtAsMjnrhwRp3fGorheLkKF6QVuts+ItwCccxNY1gLTjX8FSIljkX +XosN+kVrwEsYuts3qvv6brdIFYvYj20W3dHflxq390QMcstFvkUPSWKoequ9ThWpdEx TTfRJGCov2S0gh80Wz4Sfg/bM/DmxC8a01WmwO89FIWgyV3120CciWLVJz/d33osnxS0 5RMw== MIME-Version: 1.0 X-Received: by 10.152.3.70 with SMTP id a6mr2847063laa.71.1421494995289; Sat, 17 Jan 2015 03:43:15 -0800 (PST) Received: by 10.25.206.144 with HTTP; Sat, 17 Jan 2015 03:43:15 -0800 (PST) In-Reply-To: References: <54B93AAD.6080308@gmail.com> Date: Sat, 17 Jan 2015 11:43:15 +0000 Message-ID: Cc: "internals@lists.php.net" Content-Type: multipart/alternative; boundary=089e014940a83e8d79050cd79853 Subject: Re: [PHP-DEV] Fixing strange foreach behavior. From: rowan.collins@gmail.com (Rowan Collins) --089e014940a83e8d79050cd79853 Content-Type: text/plain; charset=UTF-8 On 16 January 2015 at 21:15, Yasuo Ohgaki wrote: > Hi Rowan, > > On Sat, Jan 17, 2015 at 1:22 AM, Rowan Collins > wrote: > >> 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) >> > > Right. foreach should not affect internal(zval) position pointer, but it > does. > > >> >> 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. >> > > Nesting foreach is strange, too. There are two issues > - array nesting does not work as it seems > - generator nesting does not work at all > > Besides generator, current behavior is strange. > It's matter of using external position pointer for arrays, isn't it? > > How about make foreach behaves sane manner by PHP 7? > It's rare that program uses internal position pointer, but > it's a basic language construct. Basic language construct > should behave intuitive way. IMHO. > My concern is, at what cost? Given how rarely used the internal pointer is, are we carrying around a chunk of extra memory with every array just on the off-chance that it will be used, or is there some magic that makes it zero-width until it's needed? Reusing it for foreach makes perfect sense if it increases performance for the majority of cases, and the only way to cover every edge-case like the one at the top of this thread would be to ban that optimisation outright. If there's some way of separating things such that the rarely used constructs take the performance hit, I'm all for it, though. Alternatively, we could achieve consistency the other way round, by making foreach() reset the internal pointer even when it *doesn't* use it, and documenting that fact like we do for certain array functions. Code relying on the current behaviour when mixing them is probably buggy anyway, because it is not well-defined, so the BC concern should be low. As for nesting, I think PHP is doing the right thing for plain arrays and non-rewindable integrators, because I would expect a for each loop to start at the beginning, thus have an implicit reset/rewind. The rewindable behaviour is awkward, though - intuitively, the iteraror needs to be able to track multiple positions simultaneously, which isn't guaranteed by the interface design. Maybe an error should be issued if the integrator is already subject of a foreach loop? -- Rowan Collins [IMSoP] --089e014940a83e8d79050cd79853--