. def delay(exp): return lambda: exp
If you look at the definition of "delay" in SICP, you'll notice that it's defined as "syntax sugar", in other words, a macro. Since Python does not have macros, you'll have to just use "lambda", because by defining "delay" as a function, you're forcing the expression "exp" to evaluate immediately. In other words, theres a crucial difference between::
delay(sys.stdout.write('evaluated\n'))
and::
lambda: sys.stdout.write('evaluated\n')
If you type in those two snippets, you'll see what I mean.
Coincidentally, I attempted a similar experiment just a couple of days ago, and here's what I came up with::
# Stream.py - Stream class inspired by SICP
class Stream(object): pass
class EndOfStream(Exception): pass
class Item(Stream): def __init__(self, current, nextf): self.current = current self.nextf = nextf
next = property(lambda self: self.nextf())
def fold(self, f, init): return f(self.current, self.next.fold(f, init))
def __getitem__(self, n): if n == 0: return self.current else: return self.next[n - 1]
def __str__(self): return '<Stream.Item: %s, ...>' % self.current __repr__ = __str__
class End(Stream): def fold(self, f, init): return init
def __getitem__(self, n): raise EndOfStream()
def _fail(self): raise EndOfStream()
current = property(_fail) next = property(_fail)
def __str__(self): return '<Stream.End>' __repr__ = __str__
Here's how it works::
Python 2.4 (#1, Dec 4 2004, 20:10:33) [GCC 3.3.3 (cygwin special)] on cygwin Type "help", "copyright", "credits" or "license" for more information. >>> import Stream >>> s = Stream.Item(1, lambda: Stream.Item(2, lambda: Stream.End())) >>> s <Stream.Item: 1, ...> >>> s.current 1 >>> s.next <Stream.Item: 2, ...> >>> s.next.current 2 >>> s.next.next <Stream.End> >>> s.next.next.next Traceback (most recent call last): File "<stdin>", line 1, in ? File "Stream.py", line 37, in _fail raise EndOfStream() Stream.EndOfStream >>> def evens(n=0): ... return Stream.Item(n, lambda: evens(n + 2)) ... >>> s = evens() >>> s.current 0 >>> s.next.current 2 >>> s.next.next.current 4
I don't know if this is useful or not, but it was an interesting exercise nonetheless.
Dave -- http://mail.python.org/mailman/listinfo/python-list