Der Blog

Greenspun's 10th Rule in the modern world

Gimbo, as many of you know, is learning Haskell, and just discovered the power and conciseness of lazy evaluation with a one-line definition of the entire Fibonacci sequence.

You can do a vaguely similar thing in Python. First we have a lazy list class:

class LazyList:
    def __init__(self):
        self._list = []

    def __getitem__(self, key):
        length = len(self._list)
        if key.__class__ == int:
            max = key
        elif key.__class__ == slice:
            max = key.stop
        if max >= length:
            for i in xrange(length-1,max):
                self._list.append(self._gen.next())
        return self._list[key]

To create the actual Fibonacci sequence, we define a subclass:

class FibList(LazyList):
    def __init__(self):
        def fibgen():
            lastfib = 0
            nextfib = 1
            yield lastfib
            yield nextfib
            while True:
                (lastfib, nextfib) = (nextfib, lastfib+nextfib)
                yield nextfib
        LazyList.__init__(self)
        self._gen = fibgen()

Then a "list" (not really a list, but looks like one) of the Fibonacci numbers is

somefibs = FibList()

and we can look up the nth Fibonacci number, and take slices of it:

>>> somefibs[0]
0
>>> somefibs[3]
2
>>> somefibs[0:3]
[0, 1, 1]
>>> somefibs[2:20:4]
[1, 8, 55, 377, 2584]

But of course this isn't a one-liner. Plus we've fallen victim to a variant of Greenspun's Tenth Rule, substituting "Common Lisp" with "Haskell 98" :)

[ Entry posted at: Sun 03 Dec 2006 16:04:11 GMT | 1 comment(s)... | Cat: Geeky ]

Andy writes:

Doesn't the append call take time proportional to the length of the list, since it has to walk down to the end of the list? So the python code above takes O(n^2) to calculate the first n fibonacci numbers, while the haskell code you are emulating does it in time O(n).

[ Mon 10 Nov 2008 20:01:56 GMT ]

Add Comment

Validate : XHTML / CSS / RSS / ATOM