delay and force in Python
Dave Benjamin
dave.benjamin at gmail.com
Wed Jan 19 10:50:33 EST 2005
Will Stuyvesant wrote:
> . 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
More information about the Python-list
mailing list