At the risk of making a complete fool of myself, I'd like to ask the smarter
brains than me to checkout the current logic in the implementation of
Iterator classes and foreach().
The current logic of foreach( $obj as $key => $val ) { ... } where $obj
implements Iterator, is:
for($obj->rewind(); $obj->hasMore(); $obj->next() ) { ... }
but it should be:
for($obj->rewind(); $obj->isValid(); $obj->next() ) { ... }
As the iterator exits the penultimate interation, next()
is called, placing
the 'pointer' on the last 'record'. But before the last record is
processed, hasMore() is called, which should return FALSE, because we
have already moved to the last record.
The implementations I have seen so far all return TRUE
from hasMore() when
positioned (i.e. current()
) on the last record - this is not logical
(Captain). It also prevents proper use of a class implementing an iterator
outside of the foreach construct.
Philip
Hello Philip,
have a look at it's dokumentation: ext/spl/spl.php
there you'll find that hasMore() needs to be checked before an access to
key()
or current()
can be done. Hence it's meaning is somewhat like
isValid().
regards
marcus
Thursday, February 26, 2004, 4:53:50 PM, you wrote:
At the risk of making a complete fool of myself, I'd like to ask the smarter
brains than me to checkout the current logic in the implementation of
Iterator classes and foreach().
The current logic of foreach( $obj as $key => $val ) { ... } where $obj
implements Iterator, is:
for($obj->rewind(); $obj->hasMore(); $obj->next() ) { ... }
but it should be:
for($obj->rewind(); $obj->isValid(); $obj->next() ) { ... }
As the iterator exits the penultimate interation,
next()
is called, placing
the 'pointer' on the last 'record'. But before the last record is
processed, hasMore() is called, which should return FALSE, because we
have already moved to the last record.
The implementations I have seen so far all return
TRUE
from hasMore() when
positioned (i.e.current()
) on the last record - this is not logical
(Captain). It also prevents proper use of a class implementing an iterator
outside of the foreach construct.
Philip
--
Best regards,
Marcus mailto:helly@php.net
Thanks Marcus
Looking at the documentation, the comments and method name (for hasMore())
do not have the same meaning - the comment is saying 'does the current
element exist?' and the method name says 'are there any more elements?'.
This makes the api very ambiguous - hasMore() and isValid() have very
specific meaning in many languages wrt iterators.
Whilst I appreciate adding an isValid() method to the Iterator interface is
not trivial (and I am loath to suggest a change this close to PHP RC
phase), but it is surely better to have an un-ambiguous api on release -
especially after all the clamouring for an interface implementation :)
Regards
Philip
Marcus Boerger wrote:
Hello Philip,
have a look at it's dokumentation: ext/spl/spl.php
there you'll find that hasMore() needs to be checked before an access to
key()
orcurrent()
can be done. Hence it's meaning is somewhat like
isValid().regards
marcus
Sorry for follow-up to myself, but it would be somewhat easier to just
rename hasMore() to isValid() and then implement hasMore() after PHP5 goes
gold.
Philip Fletcher wrote:
Whilst I appreciate adding an isValid() method to the Iterator interface
is not trivial (and I am loath to suggest a change this close to PHP RC
phase) ...
Hello Philip,
just to make it clear. hasMore() would be the exact same then isValid()
only the name would change. The semantic is already what you refer to as
isValid.
Thursday, February 26, 2004, 9:43:40 PM, you wrote:
Sorry for follow-up to myself, but it would be somewhat easier to just
rename hasMore() to isValid() and then implement hasMore() after PHP5 goes
gold.
Philip Fletcher wrote:
Whilst I appreciate adding an isValid() method to the Iterator interface
is not trivial (and I am loath to suggest a change this close to PHP RC
phase) ...
--
Best regards,
Marcus mailto:helly@php.net
Hi Marcus
Yes, the current implementation of hasMore() has an identical semantic to
isValid().
The generally understood semantic of isValid() and hasMore() are quite
different - hence the need for the rename.
Regards
Philip
Marcus Boerger wrote:
Hello Philip,
just to make it clear. hasMore() would be the exact same then isValid()
only the name would change. The semantic is already what you refer to as
isValid.
Hello Philip,
Thursday, February 26, 2004, 10:05:09 PM, you wrote:
Hi Marcus
Yes, the current implementation of hasMore() has an identical semantic to
isValid().
The generally understood semantic of isValid() and hasMore() are quite
different - hence the need for the rename.
As a side note: There is no generally understood hasMore(). Though there is
isDone() and hasMore() is sometimes used/implemented as !isDone(). The main
problem is that the original Iterator description everyone refers to doesn't
have isValid() but instead only has isDone() which doesn't fit into for(;;).
Reference: Gamma et Al, Design Patterns, 1994, Addison Wesley, p 257ff
Regards
Philip
Marcus Boerger wrote:
Hello Philip,
just to make it clear. hasMore() would be the exact same then isValid()
only the name would change. The semantic is already what you refer to as
isValid.
--
Best regards,
Marcus mailto:helly@php.net
Marcus Boerger wrote:
As a side note: There is no generally understood hasMore().
I strongly disagree - the Java Iterator has a hasNext() method which is the
exact sementic of hasMore().
Though there
is isDone() and hasMore() is sometimes used/implemented as !isDone(). The
main problem is that the original Iterator description everyone refers to
doesn't have isValid() but instead only has isDone() which doesn't fit
into for(;;). Reference: Gamma et Al, Design Patterns, 1994, Addison
Wesley, p 257ff
Hehe - I happen to have the book open on that page:)
Fortunately, PHP does not implement GOF patterns wholesale, therefore
procedural PHP constructs such as foreach need to deviate from the
isDone(). It logically requires an isValid() expression - not a hasMore()
or hasNext().
The isValid() iterator method is implemented in the Eclipse project - it
gets a mention in dispatches on phppatterns: http://www.phppatterns.com
index.php/article/articleview/50/1/1/ (just over half way down).
Regards
Philip
Thanks Marcus
Looking at the documentation, the comments and method name (for hasMore())
do not have the same meaning - the comment is saying 'does the current
element exist?' and the method name says 'are there any more elements?'.This makes the api very ambiguous - hasMore() and isValid() have very
specific meaning in many languages wrt iterators.
I agree. The semantics are fairly different. Let's not confuse them.
-Andrei
"This isn't right. This isn't even wrong."
-- Wolfgang Pauli
Hi Marcus,
Andrei Zmievski wrote:
Looking at the documentation, the comments and method name (for hasMore())
do not have the same meaning - the comment is saying 'does the current
element exist?' and the method name says 'are there any more elements?'.This makes the api very ambiguous - hasMore() and isValid() have very
specific meaning in many languages wrt iterators.I agree. The semantics are fairly different. Let's not confuse them.
I also agree strongly with the need for this to get fixed before PHP
goes to release. IMO the current hasMore() is very misleading and has
the result that people can't intuitively use it outside of the foreach()
context.
Whether the method is called isValid() or something else that makes
sense is less important to me, but providing an intuitive interface that
won't leave code users scratching their heads or submitting bug reports
for what appears to be faulty implementing iterator logic is really
important.
BTW, Iterators are awesome(!), and it's only because they are so awesome
& everyone will use them that I think this is important to address
before release.
Thanks,
Hans