Martin Weber wrote:
> On Sun, Mar 23, 2003 at 07:11:36AM +0900, Seth Kurtzberg wrote:
> 
>>On Saturday 22 March 2003 02:09 pm, Johann Hibschman wrote:
>>
>>>Seth Kurtzberg <seth / cql.com> writes:
>>>
>>>>Ruby has closures, Python does not.  Not getting into the "who's better"
>>>>argument; just citing a fact.
>>>
>>>Actually, no, that's wrong.  Python has had closures for a while now.
>>>
>>>
>>>>>>def make_adder(x):
>>>
>>>....   def adder(y):
>>>....     return x + y
>>>....   return adder
>>>....
>>>
>>>
>>>>>>a10 = make_adder(10)
>>>>>>a10(2)
>>
>>I'll have to check whether python has changed, but this example is not a 
>>closure.
> 
> 
> Mind elaborating why it isn't ? In the definition of adder the value of
> x is free, and determined by the lexical environment; make_adder defines
> it. If it wasn't a closure, a10 would depend on the value of x in the
> calling environment. It obviously doesn't. If it isn't a closure, what
> else would you call it ?
> 
> -Martin
> 
> PS: In about every scheme book I've seen, the classic closure example
> is 
> 
> (define (mk-add x)
> 	(lambda (n)
> 		(+ x n)))

That example doesn't fully explain closures. In a closure, the lambda 
function has access not just to the _value_ of x but to the same binding 
as in the outer scope, so the inner function can modify the value in the 
outer function. For example, in Ruby (or SmallTalk or Scheme) you can do 
this:

   make_counter = proc { |start|
     proc { |inc| start += inc }
   }

   counter = make_counter[0]
   p counter[3]  # ==> 3
   p counter[2]  # ==> 5

But in Python, the inner function only has access to the _object_, not 
to the original variable which refers to the object, and so you have to 
"box" the value inside an object if you want to have shared references. 
This is what you would have to do (example in Ruby. I can't make myself 
write Python code on a Saturday):

   make_counter_like_python = proc { |start|
     box = [start]
     proc { |inc| box[0] += inc }
   }

   counter_py = make_counter_like_python[0]
   p counter_py[3]  # ==> 3
   p counter_py[2]  # ==> 5

I think this is what is meant when people say Python does not have closures.