Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:50575 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 74652 invoked from network); 25 Nov 2010 21:52:25 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 25 Nov 2010 21:52:25 -0000 Authentication-Results: pb1.pair.com smtp.mail=quickshiftin@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=quickshiftin@gmail.com; sender-id=pass; domainkeys=bad Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.42 as permitted sender) DomainKey-Status: bad X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: quickshiftin@gmail.com X-Host-Fingerprint: 209.85.214.42 mail-bw0-f42.google.com Received: from [209.85.214.42] ([209.85.214.42:38270] helo=mail-bw0-f42.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 2D/90-16484-99ADEEC4 for ; Thu, 25 Nov 2010 16:52:25 -0500 Received: by bwz13 with SMTP id 13so1295955bwz.29 for ; Thu, 25 Nov 2010 13:52:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:content-type; bh=v8gTytUi2wt9hrZqCLYeysAc9ni625b95o2wLuThdeo=; b=wJIesT7Hl0d8nRTmdTM3iq4rt/cZ/manhRhA3qMI92lbUyfMZXFdhFxhXXTv96mMz7 7ALPs8mZsXHRFlPj/O+ke2peTZrox2Q/TErdQGtK5Rq43kn6iDLFZbg35RjhPV36w3At Ujbrbd+b9ip0FaTedkS1Vnrawn3J3B+uivr6k= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=urix1/Bu9d5U46Onj+NrsIB782muLWUstwoT3OdiU+mWblYHZxCQKHCarOrSRtA6Ei MdbD1WP8Mv8/yoq7V04fpd9XvBoBHfOEB+90UosHjkxd1290b4cB9TWola64fKq8p09e urPYp183HK6PFir2c3lvKSBTQoGtrB7YG/8k4= MIME-Version: 1.0 Received: by 10.204.116.4 with SMTP id k4mr1214937bkq.187.1290721942142; Thu, 25 Nov 2010 13:52:22 -0800 (PST) Received: by 10.204.150.66 with HTTP; Thu, 25 Nov 2010 13:52:22 -0800 (PST) Date: Thu, 25 Nov 2010 14:52:22 -0700 Message-ID: To: internals@lists.php.net Content-Type: multipart/alternative; boundary=001636c5975ddd7eef0495e79e5e Subject: Proposed - Integrated inner iterator support for Iterator classes From: quickshiftin@gmail.com (Nathan Nobbe) --001636c5975ddd7eef0495e79e5e Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable 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 Marcu= s regarding iterator_apply, and find myself wondering why there isn't just a= n '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 { =E2=80=A6 } 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 =3D func_get_args(); array_shift($aArgs); $aCallbackArgs =3D 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 b= e a common C function which is used to implement the interface, but that woul= d be for more educated people to decide. Classes which implement IteratorAggregate (ArrayObject for example) would then return implementors of InnerIterator, which still implement Iterator a= s 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 implemente= d 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 =3D 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 --001636c5975ddd7eef0495e79e5e--