In defence of the two-namespace rule
Harald Hanche-Olsen
hanche at math.ntnu.no
Mon Jan 24 12:16:58 EST 2000
+ "Dirk-Ulrich Heise" <hei at adtranzsig.de>:
| I don't really know what a closure is, not being
| functional-programming-minded, but could one say that a closure is a
| sort of specialization of a function, i mean, a variant of a
| function where a certain value replaces a "variable"s value?
I think you have the right idea, but you should probably replace
"value" by "binding". Now I am no computer scientist myself, so this
could be slightly wrong (but hopefully not completely so). The way I
understand it, a closure is a function together with a specific
binding for each of the non-local variables of the function. A
binding associates a location with each variable, the locations being
where values are stored. (In a purely functional language you don't
notice the distinction between bindings and values, since you cannot
change the contents of locations; you can only create new ones and
fill them with values. This is one of the reasons why it is easier to
reason about programs in functional languages.)
| And does the word "closure" play an important role outside of the
| functional programming world?
Sure. In Scheme, for example, you can create a simple counter as
follows:
(define (new-counter)
(let ((count 0))
(lambda ()
(set! count (+ 1 count))
count))))
which you would use as follows:
(define counter (new-counter))
Then the first time you call (counter) you get 1. The second time you
get 2, and so on. What happens is that (new-counter) returns a
closure, consisting of a function (the inner lambda) together with a
binding associating the variable count with a specific location. Each
time the closure is called, it updates the counter and returns the new
value.
| And what does it have to do with scopes?
Everything and nothing. The above example would look somewhat like
this in python:
def new_counter():
count=0
def counter():
count = count + 1
return count
except that would not work because of python's scoping rules. You'd
have to make it a class instead:
class Counter:
def __init__(self):
self.count = 0
def next(self):
self.count = self.count + 1
return self.count
You create a new counter using
counter = Counter()
and call it as counter.next(). [You could simplify the interface by
renaming the next method as a __call__ method, but that is beside the
point.]
You could still think of counter.next as being a sort of closure,
python terminology notwithstanding[*], in which the self variable is
bound to a specific Counter instance. And, indeed, if it referenced
any global variables, those variables would have bindings to, in the
global namespace in which the Counter class was defined.
[*] Pythonesque for this is "bound method".
But because of python's scoping rules, as we have seen the notion of
closure is not as generally useful when discussing pythonic
constructs.
Insert-clever-witticism-here-<wink>-ly y'rs,
--
* Harald Hanche-Olsen <URL:http://www.math.ntnu.no/~hanche/>
- "There arises from a bad and unapt formation of words
a wonderful obstruction to the mind." - Francis Bacon
More information about the Python-list
mailing list