Comment on PEP-0322: Reverse Iteration Methods

Stephen Horne $$$$$$$$$$$$$$$$$ at $$$$$$$$$$$$$$$$$$$$.co.uk
Sun Sep 28 23:05:37 EDT 2003


It was my intention to explain the origins of my misunderstanding,
though certainly in a slightly less than serious way and with a big
dollop of its-not-all-my-fault-you-know. I tend to screw this kind of
thing up, and it seems I have done so again here.

Everything you have said in your last reply was at least 95% valid,
but there is a point I'd still like to make...

>I never, anywhere, said "std::pair supports..."
...
>> When you say "you can in fact iterate on std::pair<T,T> with the usual
>> C++ iterator protocol" it implies to me that std::pair<T,T> provides
>> the iterator protocol itself
>
>Hey, it's not my fault you read what you want to see into what I
>posted.
...
>> But maybe I'm just being overliteral.
>
>No, you just don't know what "the usual iterator protocol" means.

I never said, anywhere, that you said that "std::pair supports..." if
we are being that pedantic, but in the life of this thread neither of
us really has been that pedantic. I quoted your exact words for the
crucial point, which were...

"you can in fact iterate on std::pair<T,T> with the usual C++ iterator
protocol"

Pedantically speaking, this is imprecise language. Most significantly,
there is no such thing as "the usual C++ iterator protocol". An
iterator may implement any one of five different iterator protocols,
and these protocols have surprisingly little in common. All require an
operator++ and all require a dereference-style operator* and that is
it.

Actually, even the operator* isn't as common as it seems - input
iterators only support read access, output ones only write access - so
the practical commonality is limited to the operator++.

But then you weren't writing a standards document, and I wasn't
reading it as a standards document.

To most C++ programmers most of the time, the words "the usual C++
iterator protocol" don't have the pedantic meaning set by the C++
standard - they are not just about having an operator++. They have a
somewhat more pragmatic meaning, which includes the usual means of
obtaining iterators from containers. std::pair *is* a container in the
general sense of containing other objects, even though in the C++
standards document context it is not formally considered a container.

Of course there is room for misinterpretation in virtually any piece
of writing - criticism of your choice of words was certainly
intentional, but meant to be lighthearted.

But if you really believe that I "read what [I] want to see into what
[you] posted" then I'm afraid you're wrong. I saw an implication which
you never intended, but that was right at the start when I had no
reason to "want to see" anything in particular.

I do have a certain history in this kind of
minor-misunderstanding-gets-overblown storyline, as Alex Martelli I
think can confirm if he's still following the thread. Actually, he'll
probably say you should consider yourself lucky that it only got this
bad ;-)

Anyway, I'm in no doubt that I'm primarily (probably entirely)
responsible for the 'overblown' part especially with my previous post.
I appologise for that.


>This whole discussion started out talking about what the Python
>protocol for manipulating iterators should be.  The fact that
>iterators must themselves have an __iter__ method in Python may just
>be making this more confusing than it needs to be.

We may think of '__iter__' as part of the iterator protocol but,
pedantically speaking, it is no more part of the Python iterator
protocol than 'begin' is part of the C++ iterator protocol.

Iterators don't have to have an '__iter__' method in Python. Iterators
only have to have a 'next' method. It is the iterable object that
implements '__iter__'. And, as with getting C++ iterators from 'begin'
etc, even that is a convention rather than a requirement.

Sometimes iterators do have an '__iter__' method, but that normally
just returns self - it's a quick-fix convenience for when iterators
end up in a context where an iterable object is expected.

I guess our mindsets aren't so different that we can't make similar
mistakes ;-)


BTW - there's no reason why an iterator can't have additional methods
beyond those required for the iterator protocol. So a container class
could, for instance, support the following...

  for i in iter (container).range (begin, end).reverse () :
    ...

Simply by defining its iterator class as something like...

  class Iter (object) :
    def __init__ (self, p_Src) :
      "Keep ref to container to iterate, plus other setup stuff."
      self.Src = p_Src
      ...

    def __iter__ (self) :
      "Allow iterator to behave as iterable for convenience"
      return self

    def range (self, p_Begin, p_End) :
      "Set restriction on range to be iterated"
      ...
      return self

    def reverse (self) :
      "Set reverse-order iteration mode"
      ...
      return self

    def next (self) :
      "Get next item"
      ...

Which reminds me of Paul Foleys post in "Thoughts on PEP284",
Message-ID: <m2eky8dtny.fsf at mycroft.actrix.gen.nz>, about Lisp-like
for-loops - though actually it's really just a minor variation of what
Raymond suggested right from the start.

Hmmm - possibly this suggestion should be made closer to the root.


-- 
Steve Horne

steve at ninereeds dot fsnet dot co dot uk




More information about the Python-list mailing list