text: 12 replies on
  1 page.
  Most recent reply:
  Aug 25, 2005 1:13 PM
  by
  Kay Schluehr
  However, if you know of other writings that actually analyze the differences between the two languages (rather than just rant about how great one or the other is), please add them below.
  Anyone interested in this recipe might also like to read a recent book, "Hackers and Painters: Big Ideas from the Computer Age", by Paul Graham (2004).Though the book is mostly a non-technical discussion of programming principles and practices (generally lionizing Lisp) there is an appendix (pp. 195-99) which compares the __call__ version above to even simpler solutions in other languages.Though his example is just a generated function with maintained state, rather than a "generator" (ie a function with a "yield" call), it explains exactly why some people appreciate other, more powerful languages.I disagree with him: The Python example is only slightly more complicated, and it is vastly easier for a non-expert user to comprehend. The implicitly lexical variables do not exactly aid readability.However, Graham is not unkind to Python, and this book is definitely worth reading for anyone with an interest in the utility of programming languages.I'm pointing that out because this recipe has caused some big ideas to gel in my mind. After studying this complicated recipe, I suddenly "get" what Python is doing with functions. Tes, the version in the comment is definitely the way I would code it in practice, but I'm glad to see the complex one.In case you don't have the book, here are his examples. Python first:class foo: def __init__(self, n): self.n = n def __call__(self, i): self.n +=1; return self.nObviously, this could yield self.n instead.The Java solution is a pain, but in Javascript:function foo(n) { return function(i) { return n += 1 }}Smalltalk has strange syntax, but at least has the transparency of the Python version:foo: n |s| s := n. ^[:i| s := s+i. ]Perl has an implicit return statement:sub foo { my ($n) = @_; sub {$n += shift}}Ruby is the clearest, but with strange delimiters:def foo (n) lambda {|i| n += i} endLisp is easily the least cluttered:(defun foo(n) (lambda (i) (incf n i)))The author also lists 2 other Python solutions which work, and 2 which do not work:def foo(n): class accumulator: def __init__(self, s): self.s = s def inc(self, i): self.s += i return self.s return acc(n).inc# anddef foo(n): s = [n] # The list holds a copy of n def bar(i): s[0] += i return s[0] return barAnd these 2 do *not* work:def foo(n): return lambda i: return n += 1# nordef foo(n): lambda i: n += 1The author guesses that Python will one day allow something like these, but only the Python class-based version allows easy access to n. So in fact, what to some is a flaw in Python can be a feature to others.I hope somebody learns as much from these examples as I have. Functional programming suddenly makes much more sense to me.
  def foo(n): class accumulator: def __init__(self, s): self.s = s def inc(self, i): self.s += i return self.s return acc(n).inc
  class accumulator: def __init__(self, s): self.s = s def __call__(self, i): self.s += i return self.s
  def accum(n): incr = yield # wait to get the first incr to be sent in while 1: n += incr incr = yield n # return the new value, wait for next incr
  >>> s = accum(0)>>> s.next() # setup boilerplate :(>>> s.send(3)3>>> s.send(1)4
  def foo(n): def bar(i,n=n): n+=i # state change return n return bar
  def foo(n): # pure functional lambda i:i+n