[Tutor] (OT) Flame wars

Danny Yoo dyoo at hkn.eecs.berkeley.edu
Tue Nov 7 00:18:00 CET 2006



On Mon, 6 Nov 2006, Chris Hengge wrote:

> I may have just missed the point to your attempt to derail this 
> conversation =P

Hi Chris,

Ah!  Are we talking about regular expressions anymore?

No?

Good.  *grin*



> Why do all that when you can just
>
> str = "Hello World"
> print str * 2

Let me do a more substantial example.  As you know, Python's for loop 
works on "iterables":

#####################
>>> for x in list("hello"):
...    print x
...
h
e
l
l
o
#####################

We're running a for loop across a list of characters.  In this case, our 
list is iterable.  (We could iterate directly on the string itself, but 
let's stick with lists for the moment.)  An "iterable" in Python is 
something that can give us an iterator.

###############################
>>> my_iterator = iter(list("hello"))
###############################


An iterator is something that responses to next() requests until we 
consume everything:

#################################
>>> my_iterator.next()
'h'
>>> my_iterator.next()
'e'
>>> my_iterator.next()
'l'
>>> my_iterator.next()
'l'
>>> my_iterator.next()
'o'
>>> my_iterator.next()
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
StopIteration
##################################


So there's a few layers of indirection here.

     iterable -> iterator -> elements


Ruby takes a different approach: they also have an iterator protocol, but 
what they require is something that provides an each() method.  For 
example:

####################################################
irb(main):002:0> 'hello'.split(//).each {|c| puts c}
h
e
l
l
o
####################################################

This each method takes in a code block, and runs it on every element in 
the thing we're iterating across.  The iterable itself provides the 
looping mechanism instead of the client code.


The concept sorta looks like this in Python:

#######################################################
class MyString:
     def __init__(self, s):
         self.s = s

     def each(self, f):
        i = 0
        while i < len(self.s):
            f(self.s[i])
            i = i + 1

MyString("hello").each(lambda c: sys.stdout.write(c + '\n'))
########################################################

This, too, "iterates" across our iterable.

The one handling the control flow is the 'each' method, which is a little 
wacky to think about at first.  The Ruby folks make this work because 
their syntax is custom tailored for this pattern, so it's easier to read 
and write.

I'm probably not doing it much justice with my ugly examples.  *grin*


More information about the Tutor mailing list