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