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