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 ]