Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:50646 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 62073 invoked from network); 28 Nov 2010 01:22:10 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 28 Nov 2010 01:22:10 -0000 X-Host-Fingerprint: 99.64.124.23 adsl-99-64-124-23.dsl.ipltin.sbcglobal.net Received: from [99.64.124.23] ([99.64.124.23:24372] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id DE/F3-29052-1CEA1FC4 for ; Sat, 27 Nov 2010 20:22:10 -0500 Message-ID: To: internals@lists.php.net Date: Sat, 27 Nov 2010 20:22:03 -0500 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.12) Gecko/20101027 Lightning/1.0b2 Thunderbird/3.1.6 MIME-Version: 1.0 References: In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Posted-By: 99.64.124.23 Subject: Re: Proposed - Integrated inner iterator support for Iterator classes From: alecgorge@gmail.com (Alec) I love it. This should get implemented. On 11/25/2010 4:52 PM, Nathan Nobbe wrote: > Hi everyone, > > I've been taking another look at iterators lately, and compiled trunk and > started experimenting with traits. I also looked at an old mail from Marcus > regarding iterator_apply, and find myself wondering why there isn't just an > 'apply' method as part of the Iterator hierarchy itself. > > Although PHP had support for the pseudo-type callback when the Iterator > interface was introduced, I'm not sure why an 'apply' function would have > been omitted from the original Iterator interface. Clearly with > iterator_apply out there, there is no functional gain by adding a method > into the Iterator hierarchy, however I think it would be more cohesive with > the OO paradigm the Iterator hierachy presents .. there is already > array_walk and friends for the global function gang :) And now with > closures the idea of an 'apply' method is even more enticing .. yes I'm > thinking of Javascript code like JQuery's each() ... > > > I can tell why it wouldn't have been added after the original interface was > in the wild though, because changing the interface would break tons of > client code. However a second interface could be added and all client code > would continue to function > > > interface InnerIterator > > { > > function apply($mCallback [, mixed $...]); > > } > > > Rather than extend Iterator, InnerIterator should be left independent so it > can be incorporated into implementors of OuterIterator (see below). Then > concrete Iterator(s) could implement this new interface as well > > > class ArrayIterator implements Iterator, InnerIterator { … } > > > I'm not sure what the best implementation at the engine level would be, but > with the advent of traits that would clearly be one option, a simple > implementation could be something like > > > trait InnerIteratorImpl > > { > > public function apply($mCallback) > > { > > $aArgs = func_get_args(); > > array_shift($aArgs); > > $aCallbackArgs = array_merge(array($this), $aArgs); > > return iterator_apply($this, $mCallback, $aCallbackArgs); > > } > > } > > > Then the ArrayIterator definition could become > > > class ArrayIterator implements Iterator, InnerIterator > > { > > use InnerIteratorImpl; > > ... > > } > > > I hardly doubt this is necessary inside the engine, as I'm sure there can be > a common C function which is used to implement the interface, but that would > be for more educated people to decide. > > > Classes which implement IteratorAggregate (ArrayObject for example) would > then return implementors of InnerIterator, which still implement Iterator as > they originally did. Classes which implement OuterIterator could now also > implement InnerIterator as well, and the 'apply' method in that case can > simply delegate to the wrapped Iterator as they currently do for implemented > Iterator methods. > > > class CachingIterator implements OuterIterator, InnerIterator > > { > > public function apply($mCallback) > > { > > return $this->getInnerIterator()->apply(func_get_args()); > > } > > } > > > A quick example from userspace with the addition > > > $oArrayObj = new ArrayObject(array(5, 4, 3, 2, 1)); > > $oArrayObj->getIterator()->apply(function(Iterator $oIt) { > > var_dump($oIt->current()); > > return true; > > }); > > > At the end of the day it's just syntactic sugar since iterator_apply is > there, but in my book it would be welcome sugar ;) I would also argue that > even with traits, implementing this notion in userspace is slower (needless > conversion) and messy, imagine a subclass of ArryObject for example that > implements InnerIterator, inside of getIterator, it has to convert the > ArrayIterator to a new userspace class InnerArrayIterator or some such, > which implements InnerIterator, before returning it. > > > Your thoughts appreciated! > > > -nathan >