Mark M. Hoffman on 15 Mar 2010 15:12:24 -0700


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: closures


Hi:

Thank you.  Just a couple comments in line below...

* Michael Bevilacqua-Linn <michael.bevilacqualinn@gmail.com> [2010-03-15 17:36:18 -0400]:
>    While HOP probably does a better job of explaining closures than I do...
> 
>    When someone says that a language 'has closures', what they generally seem
>    to mean is that the language has first-class functions (usually, more
>    accurately, procedures since most practical languages allow side effects,
>    but that distinction doesn't seem to be made much) that 'close over' their
>    surrounding scope.*
> 
>    A first-class function (or procedure) means that there's a facility in the
>    language that allows you to create procedures at execution time, store a
>    reference to them in a variable, basically treat them as you would any
>    other piece of data that your program is working with.*
> 
>    Like I mentioned above, the 'closure' refers to the procedure 'closing
>    over'* the scope that it was created in, which just means that the free
>    variables in the procedure are bound in the environment that existed when
>    the closure was created.* This sounds impressive and hard to grok, but
>    it's actually pretty clear with an example, so let's see if I can fit one
>    in here.
> 
>    Let's say we have the following psuedocode, in a language that allows
>    nested procedure definitions.
> 
>    defproc outerProcedure(){
>    * def x = 1
>    * def y = 1
>    * print "In outerProcedure"
>    * print x
>    * print y
>    *
>    * defproc innerProcedure(){
>    ***** def y = 2
>    ***** print "In innerProcedure"
>    ***** print x
>    ***** print y
>    *** }
>    }
> 
>    An easy way to visual the lexical scope as this program executes is as a
>    linked list of symbol tables.* When x and y are defined in outerProcedure,
>    they're placed into a symbol table along with their values.* When
>    innerProcedure executes, a new symbol table is created and y is placed in
>    that symbol table (along with its new value).* This second table also
>    contains a link back to the table for outerProcedure.
> 
>    To look up the value that a variable is bound to at any given point in the
>    program, start at the bottom-most symbol table and see if there's a
>    binding for the variable, and then work your way up the chain.* So in this
>    case, in innerProcedure, we'd get a value of 2 for y and 1 for x, just
>    like we'd expect.*
> 
>    So a closure is a structure that contains not only the procedure that
>    you've created, but a way to get at the scope it was defined in.*

... even after that original scope is gone, e.g. if a reference was passed out
of "outerProcedure" and lives on afterward.

It doesn't seem to me that nested procedure definitions are strictly necessary
to create a closure - so long as a function is created whose variables are bound
according to the scope at the time of creation.

> I tend
>    to think of it as having not only the chunk of code, but a linked list of
>    symbol tables like I described above (though I can't imagine that's how
>    it's implemented anywhere outside of CS class...)* You can then pass this
>    structure around, add new layers of scope to it, etc.*
> 
>    So while C function pointers and closures may serve the same purpose some
>    of the time (you could probably use either to, say, pass a sorting
>    algorithm into a procedure), closures are a lot more powerful, and can
>    help lead to better factored code.* Since they carry their scope with
>    them, you can be a lot more sure that some piece of code a hundred
>    thousand lines away hasn't reached in and mucked with some of your state.*
> 
>    Also, HOP is worth a browse even for non perl people (like myself).
> 
>    Thanks,
>    MBL
> 
>    * I've never been able to figure out what, if any, this has to do with
>    mathematical closures.* I think the term might just be overloaded?
> 
>    On Mon, Mar 15, 2010 at 4:35 PM, <[1]mjd-phillylambda@plover.com> wrote:
> 
>      > So I'd like to test my understanding with this group...
>      >
>      > * * * int x;
>      >
>      > * * * void foo(int x);
>      > * * * void baz(void (*F)(void));
>      >
>      > * * * void callback(void)
>      > * * * {
>      > * * * * * * * foo(x);
>      > * * * }
>      >
>      > * * * void bar(void)
>      > * * * {
>      > * * * * * * * baz(&callback);
>      > * * * }
>      >
>      > C doesn't "support" closures, but the code above has one.
> 
>      Only in a trivial sense. *C doesn't support nested function scopes, so
>      in C one can't construct an interesting example of closures or of
>      their failure in C. *I wanted to construct a C example for you, but
>      none of my constructions made sense as C.
> 
>      To not-answer your question:
>      > The above is a closure, if you could do such a thing in C.
> 
>      I think the only thing you could usefully do with this question is to
>      unask it. *Trying to understand closures by studying the non-behavior
>      of the nonexistent closures of C is pointless.
> 
>      If you like Perl, I suggest that you read chapter 3 of "Higher-Order
>      Perl", available for free download at:
> 
>      * * * *[2]http://hop.perl.plover.com/
> 
>      I think the explanation there is both clear and rigorous.
> 
>      If you like some other language that has closures, I suggest you ask
>      for an example in that language.
> 
>      If you only like C, I suggest you either forget about closures
>      (because C doesn't have them) or learn to like some language that does
>      have them.
>      > The word closure
>      > is used here because we create an instance of foo() over which x is
>      "closed".
>      >
>      > Do I have it right so far?
> 
>      No:
> 
>      * You have not created an instance of foo, or indeed of anything.
>      *Functions always have static duration in C. *Instances of functions
>      *are created at compile time, and not afterward.
> 
>      * The jargon is that the function is closed over the variable, not the
>      *other way around.
>      > I would appreciate it if someone could propose a few problems which
>      > are trivial to solve with closures, but difficult without.
> 
>      a. Implement an object-oriented programming system. *Closures make
>      * adequate objects. *This is discussed in detail in _Structure and
>      * interpretation of Computer Programs_, should you want to know more.
> 
>      b. Almost anything in _Higher-Order Perl_; see the table of contents.

Thanks & regards,

-- 
Mark M. Hoffman
mhoffman@lightlink.com


  • Follow-Ups:
    • Re: closures
      • From: Michael Bevilacqua-Linn <michael.bevilacqualinn@gmail.com>
  • References:
    • closures
      • From: "Mark M. Hoffman" <mhoffman@lightlink.com>
    • Re: closures
      • From: mjd-phillylambda@plover.com
    • Re: closures
      • From: Michael Bevilacqua-Linn <michael.bevilacqualinn@gmail.com>