Sunday, October 17, 2010

Lazy list is Python generator

Functional programmers often miss lazy list when coding in a popular language. In some circumstances, they can make do with Python generators. An even better news is that from 2.3, Python provides  itertools library, which contains the old friends: cycle, repeat, takeWhile, dropWhile ... such that
takeWhile (<10) [1..]
translates to
>>> list(takewhile (lambda x:x<10,count(1)))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Now if the library is short for your need, we can resort to yield statements in python. Suppose we want to enumerate ways of splitting a list into two parts.
>>> list(splits ([1,2,3]))
[([1, 2, 3], []), ([2, 3], [1]), ([1, 3], [2]), ([3], [1, 2]), ([1, 2], [3]), ([2], [1, 3]), ([1], [2, 3]), ([], [1, 2, 3])]
In Haskell it will be
splits [] = [([],[])]
splits (x:xs) = concatMap expand $ splits xs
                where expand (a,b) = [(x:a,b),(a,x:b)])
In Python it will be
def splits(l):
    if l==[]:yield ([],[])
    else:
        x,xs=l[0],l[1:]
        for (a,b) in splits(xs):
            yield ([x]+a,b)
            yield (a,[x]+b)
Quite literate, isn't it!

No comments:

Post a Comment