Alternative iterator syntax

Rainer Deyke root at rainerdeyke.com
Wed Feb 21 15:29:21 EST 2001


"Huaiyu Zhu" <hzhu at users.sourceforge.net> wrote in message
news:mailman.982769240.31345.python-list at python.org...
> Following suggestion by Jeff Petkau <jpet at eskimo.com>,
> (http://mail.python.org/pipermail/python-list/2001-February/029944.html),
> here is a different proposal for iterators.
>
> Like the colon-syntax proposal, it achieves the following
>
> 1. It provides an extensible iterator interface without pretending to
>    provide random access to elements.
> 2. It resolves the endless "i indexing sequence" debate.
> 3. It allows performance enhancements to dictionary iteration.
> 4. It is completely backward compatible.

5. It will allow iteration over "sequences" longer than 'sys.maxint'.

> They MAY but NEED NOT define a __len__ method, which may or may not
> return semantically correct result.

What is the point in allowing a semantically incorrect '__len__'?

>   If A defines __next__, the above is interpreted as the equivalence of
>   (__got is an invisible variable):

<snip>

>   Else if A defines __list__, then "for x in A:" is interpreted as "for
>   x in A.__list__():".  Note that every list is an iterator (see below).

(see below)

>   Else if A is a callable object, then "for x in A:" is interpreted as
>   "for x in A():".

Won't this interfere with existing user-defined sequences that are also
callable but don't support the iterator protocol?

> 2. The in operator:
>
>   Consider the expression
>     (a, b, c, ...) in A:
>
>   If A defines __contains__, the above is interpreted as the equivalence
>   of:
>     A.__contains__((a,b,c, ...))
>
>   Else if A defines __list__, then "x in A" is interpreted as "x in
>   A.__list__()".  Note that every list is an iterator (see below).

Why is '__next__' not used?

> Applications to Builtins and Other Common Situations:
>
> 1. Sequences.  The builtin sequence types (list, tuple, string) are
>   changed to iterators by adding the three magic methods __next__,
>   __contains__ and __list__.  The following is always true:
>
>     x.__list__() == list(x)

This is really really bad.  Iterators have state.  Tuples and strings do
not.  Consider the following:

a = 'Hell, O world!'
a.__next__()
b = 'Hell, O world!'
print '"%s", "%s", %d' % (a, b, a == b) # Are they the same?
print a.__next__(), b.__next__()

Don't do it.  Instead, either the original iteration protocol should be left
in place as backup, or there should be some automagic way of generating
iterators form sequences.


>   In addition, Each sequence object x defines two attributes (indexes,
>   items) that are themselves iterators.  The arity of indexes is 1, that
>   of items is 2.


NOOooooOoooOo!!!!!!!!

>
>     x.indexes.__list__() == range(len(x))

'range(len(x))' returns a list of integers, not a list of 1-tuples.  This
may not be significant for sequences, but consider mappings:

> 2. Mappings.  Each mapping object x defines three attributes (keys,
>   values, items) that are callable iterators.  The arity of keys and
>   values is 1, that of items is 2.

The following is currently valid Python code:

d = {('cheese', 'shop') : ('dead', 'parrot') }

for a, b in d.keys():
  print a, b # Prints 'cheese shop'

for a, b in d.values():
  print a, b # Prints 'dead parrot'

Setting the arity of 'keys' and 'values' to 1 breaks this.

> 4. The Iterator class.  An iterator class could be included with
>   standard python, so that one could write:
>
>     a = Iterator([1,2,3])       # Or a = Iterator(); a.__list__ = [1,2,3]

I thought the '__list__' attribute of iterators was a method that returns a
list, not a list.

> 1. Following Python tradition, using magic methods is preferred to
>    adding special syntaxes.  Special syntaxes are only added if existing
>    syntax space is not large enough to call these magic methods, which
>    is not the case here.

I thought all magic methods were merely ways of implementing the
functionality of built-in types in classes, i.e. e.g. '__add__' is never
called directly, but merely used by the built-in types 'class instance' to
implement the syntax 'a + b'.

> 2. Iterators should not be limited to what they can emit, so the items
>    should be allowed to be tuples of any desired arity.  For example, an
>    iterator over spatial points may be used as "x,y,z in points".  This
>    generality is not possible with the colon based special syntax that
>    is only applicable to lists and dicts.

Why must iterators emit tuples at all?

> Appendix: Application of the __arity__ syntax to general tuple unpacking.
>
> This is independent of the iterator issue, but it is closely related to
> the outputs of iterators.  The __arity__ syntax proposed above appears
> to also solve tuple unpacking problems elsewhere.

<snip>

I am totally against the '__arity__' syntax.   It only seems to replace one
thrown exception for another.  Besides, in my experience, code like the
following is not uncommon:

def return_tuple(n):
  return (0,) * n

a, b = return_tuple(2)
x, y, z = return_tuple(3)


Such code could not use '__arity__', reducing it to special case syntax
sugar.


--
Rainer Deyke (root at rainerdeyke.com)
Shareware computer games           -           http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor





More information about the Python-list mailing list