Google Groups Home
Help | Sign in
A question (confusion) about closure
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 1 - 25 of 66 - Collapse all   Newer >
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
Samik  
View profile
 More options May 2, 4:31 am
Newsgroups: comp.lang.lisp
From: Samik <sam...@gmail.com>
Date: Fri, 2 May 2008 01:31:18 -0700 (PDT)
Local: Fri, May 2 2008 4:31 am
Subject: A question (confusion) about closure
Hi,

I have a confusion regarding closure and its definition. As per Paul
Graham:

When a function refers to a variable defined outside it, it’s called a
free variable. A function that refers to free lexical variable is
called a closure.

However as per CLHS a closure or lexical closure is:

lexical closure n. a function that, when invoked on arguments,
executes the body of a lambda
expression in the lexical environment that was captured at the time of
the creation of the lexical closure, augmented by bindings of the
function's parameters to the corresponding arguments.

lexical environment n. that part of the environment that contains
bindings whose names have lexical scope. A lexical environment
contains, among other things: ordinary bindings of variable names to
values, lexically established bindings of function names to functions,
macros, symbol macros, blocks, tags, and local declarations (see
declare).

Can any pro lisper kindly help me?

Thanks,
Samik
Blog: http://lispsamik.blogspot.com/


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
xahlee@gmail.com  
View profile
(2 users)  More options May 2, 5:02 am
Newsgroups: comp.lang.lisp, comp.lang.functional
From: "xah...@gmail.com" <xah...@gmail.com>
Date: Fri, 2 May 2008 02:02:14 -0700 (PDT)
Local: Fri, May 2 2008 5:02 am
Subject: Re: A question (confusion) about closure
There is no universal definition of the concept of closure in the
context of programing languages.

Basically, if your language can define a function, and maitain a
permanent internal variable inside, it's closure.

For example, if you define a global var, and your function use access
and or set that global var, your function will be able to maintain a
state.

However, we all know global vars are bad because, for example, you
have this big pool where everyone and every function accesses... it's
hard to maitain and could be over-ridden by mistake...

So, a crude way to remedy this, is by following a convention, such
that any global var who's name starts with a 2 underscore is meant to
for special use. So, this way, you can have global vars __this ,
__that , __x, etc, and your function can call them. Now your function
can maintain a state, while the typical problem with using global vars
is avoided by a naming convention.

Now, effectively, your function is said to have “closure”. Typically,
that word is used when the language provide means to allow function to
have a state without the above hackish method. However, it's no more
complicated than that. In fact, it is effectively the only means to
implement closure. If the language hides such global vars from user,
and provide transparent ways when you create or access them inside
your function without the __ prefix, that's closure.

Once a functional language's funtion's has states, that is, having
closure, it is natural to extend the concept to become “objects” as in
Object Oriented Programing.

When you start to program in a way of closures, that is, a function
uses permant internal variables to maintain states, and you have many
functions like that, naturally, you might systematically explore this
paradigm. Namely, instead of just one or two permanent internal
variables, each of your function uses tens of such permanent internal
vars. This is the starting concept of so-called Object Oriented
Programing.

For detail and further explanation, see:

What are OOP's Jargons and Complexities
 http://xahlee.org/Periodic_dosage_dir/t2/oop.html

--------------

Note: The terminology “Closure” is actually a very bad terminology. It
spreads endless confusion and non-understanding. See:

Jargons of Info Tech industry
http://xahlee.org/UnixResource_dir/writ/jargons.html

Math Terminology and Naming of Things
http://xahlee.org/cmaci/notation/math_namings.html

  Xah
  x...@xahlee.org
http://xahlee.org/


On May 2, 1:31 am, Samik <sam...@gmail.com> wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
John Thingstad  
View profile
 More options May 2, 6:44 am
Newsgroups: comp.lang.lisp
From: "John Thingstad" <jpth...@online.no>
Date: Fri, 02 May 2008 12:44:36 +0200
Local: Fri, May 2 2008 6:44 am
Subject: Re: A question (confusion) about closure
På Fri, 02 May 2008 10:31:18 +0200, skrev Samik <sam...@gmail.com>:

In a nutshell.

(let ((val const))
   (defun func (...)
     (setf val ...)
     ...))

Func sees val but outside the scope it doesn't.
The trick is that the lexical environment survives the oldest function  
referring to it.
This becomes particularly interesting when returning a anonymous function.
(let ((val const))
   (defun func (...)
     (setf val ...)
     (lambda (...) ...)))

Where lambda too knows val.

For a practical example study study the CL-PPCRE library.

--------------
John Thingstad


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Alan Crowe  
View profile
 More options May 2, 8:02 am
Newsgroups: comp.lang.lisp
From: Alan Crowe <a...@cawtech.freeserve.co.uk>
Date: 02 May 2008 13:02:48 +0100
Local: Fri, May 2 2008 8:02 am
Subject: Re: A question (confusion) about closure

Samik <sam...@gmail.com> writes:
> Hi,

> I have a confusion regarding closure and its definition. As per Paul
> Graham:

> When a function refers to a variable defined outside it, it's called a
> free variable. A function that refers to free lexical variable is
> called a closure.

I'm not clear on what you are asking about. Are your
concerns about Common Lisp or English?

Graham's first sentence clunks. The fault is the use of the
pronoun "it" twice, with different referents. The sentence
should be

    When a function refers to a variable defined outside it,
    we call the variable a free variable.

One reason that it is important to write is that one learns
how hard it is to express oneself clearly. Armed with this
knowledge one can take a realistic attitude to other authors
writings. Graham was not entirely clear. Diagnose the
problem using the skills one has developed for making ones
own writing clear to others. Work out what he meant and move
on.

The REPL is your friend. Chat with the REPL:

 CL-USER> (defparameter *op-list*
           (let ((count 0))
             (list (lambda()(incf count))
                   (lambda()(decf count))
                   (lambda()(setf count 0)))))
*OP-LIST*
CL-USER> (funcall (first *op-list*))
1
CL-USER> (funcall (first *op-list*))
2
CL-USER> (funcall (first *op-list*))
3
CL-USER> (funcall (second *op-list*))
2
CL-USER> (funcall (third *op-list*))
0
CL-USER> (funcall (second *op-list*))
-1
CL-USER> (funcall (second *op-list*))
-2

Notice the use of assignment, directly with setf, and
lurking inside incf

CL-USER> (macroexpand-1 '(incf x))
(LET* ((#:G1626 1) (#:G1625 (+ X #:G1626)))
  (SETQ X #:G1625))

The use of assignment is essential.

Your state machine example in your blog post does no
assignment and only accidently appears to work. I found it
very confusing. I'll explain why.

     Consider the following state machine; it has two states
     S0 (represented as 0) and S1 (represented as 1). Here
     is the logic that it performs, if the current state of
     the machine is S0 and input is 0 it remains in S0 else
     machine goes to state S1. If the current state of the
     machine is S1 and input is 0 it changes the state to S0
     else it remains in state S1. This machine accepts 1 and
     0 as input. Also note that this machine initializes at
     state S0.

     Here is the code:

     (let ((s0 0) (s1 1) (state 0))
       (defun input-action(in)
         (if (eq state in)
             state
             (if (eq state s0)
                 s1
                 s0))))

(I'm no expert on HTML but I've put the indentation back
in. I think that you need to use the <pre> tag to preserve the leading
white space. Is there another tag that does the job?)

What confused me was trying to reconcile the description
with the code

    (let ((s0 0)(s1 1) ....

What pops into my head is that you have two state variables
s0 and s1 and four states.

s0 = 0, s1 = 0
s0 = 0, s1 = 1
s0 = 1, s1 = 0
s0 = 1, s1 = 1

Actually no. You are doing something very different, better
written

(defconstant s0 0)
(defconstant s1 1)

(let ((state 0))
  (defun input-action (in) ...)
  (defun report () state))

With an extra function, to directly examine the state, you
can see that it doesn't change. The point is covered up
because you are encoding the input as a set of numbers {0,
1} and encoding the states as a set of numbers {0, 1}, and,
oh look, its the same set.

Sometimes you have a particular encoding handed to you, for
example, by the designers of a microprocessor, but this is
rather specialised. In Common Lisp, it is best to use
symbols directly.

CL-USER>
(let ((state 'off))
  (declare (type (member on off) state))
  (defun input-action (input)
    (declare (type (member push nil) input))
    (setf state
          (case input
            (push (case state
                    (on 'off)
                    (off 'on)))
            ((nil) (case state
                     (on 'on)
                     (off 'off)))))))

; Converted INPUT-ACTION.
INPUT-ACTION

CL-USER> (dolist (input '(nil nil push nil push push push))
           (print (input-action input)))

OFF
OFF
ON
ON
OFF
ON
OFF
NIL

Notice my use of declarations. They are not necessary. If
you were writing real code you would either leave them out
or use a deftype to abbreviate them. However they are better
than comments as decoration for code posted online because
they have a formal meaning.

Notice that CASE clauses are headed by lists of things,
which is just what you want for state machines. A symbol
works as a designator for a list with one item, that
symbol. Which is very convenient, except that NIL is the
empty list and doesn't match anything. You can abbreviate
((push) ...) as (push ...), but you cannot abbreviate ((nil)
...) as (nil ...)

Your example and my example both suffer from the problem of
being too simple. Since they don't really do anything it is
hard for the reader to get the point and see how they do
what they do. The example needs to be more complicated. But
just a tiny bit more complicated, or the complications will
conceal the point. I'm going to drop out at this
point. Writing is hard. Writing requires practise. Please
feel encouraged to write another blog post.

Alan Crowe
Edinburgh
Scotland


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal J. Bourguignon  
View profile
 More options May 2, 11:25 am
Newsgroups: comp.lang.lisp
From: p...@informatimago.com (Pascal J. Bourguignon)
Date: Fri, 02 May 2008 17:25:23 +0200
Local: Fri, May 2 2008 11:25 am
Subject: Re: A question (confusion) about closure

;; John's example:
(let ((val const))   ; local, lexical variable
  (defun func (...)  ; lexical closure
    (setf val ...)   ; val is free in func
    ...))

(defvar *val* 'value) ; global, dynamic variable
(defun gunc (...)     ; a closure too!
   (setf *val* ...)   ; *val* is free in gunc.
   ...)

Now, technically, in Common Lisp a function whose free variables are
all global, dynamic variables wouldn't be called a closure, since
these variable are not really enclosed in an environment with the
function: they just lie in the global environment, along these
functions, and since it's considered a closed universe, there's no
outside to be considered enclosed.   When everybody is something,
there's no point in naming it.

Even a function without free variables could be considered a closure,
if the implementation encloses it in an empty environment, just for
the sake of  homogeneity with the other closures.  But CL leaves the
implementations free to optimize this case out.

--
__Pascal Bourguignon__


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
joswig@corporate-world.li sp.de  
View profile
 More options May 2, 7:11 pm
Newsgroups: comp.lang.lisp
From: "jos...@corporate-world.lisp.de" <jos...@corporate-world.lisp.de>
Date: Fri, 2 May 2008 16:11:11 -0700 (PDT)
Local: Fri, May 2 2008 7:11 pm
Subject: Re: A question (confusion) about closure
On May 2, 11:02 am, "xah...@gmail.com" <xah...@gmail.com> wrote:

> There is no universal definition of the concept of closure in the
> context of programing languages.

Fortunately there is. You just have to look it up.

> Basically, if your language can define a function, and maitain a
> permanent internal variable inside, it's closure.

> For example, if you define a global var, and your function use access
> and or set that global var, your function will be able to maintain a
> state.

Closures have nothing to do with global vars. Your attempt
to explain it does not help.

We can have different closures with the same function
and each has different variable bindings. Your global-variable-model
does not provide that.

(defun make-thing (name)
   (flet ((local-function (message &rest args)
            (case message
              (:print (format t "Hi, I am ~a" name))
              (:rename (setf name (first args))))))
     #'local-function))

(make-thing "Red Chair") returns a closure.
(make-thing "Blue Chair") returns another closure.

Let's look inside:

? (describe (make-thing "Red Chair"))
#<COMPILED-LEXICAL-CLOSURE LOCAL-FUNCTION #x2AA04BE>
Name: LOCAL-FUNCTION
Inner lfun: #<Compiled-function LOCAL-FUNCTION (Non-Global)
#x2A9AFD6>
Closed over values
(0): "Red Chair"

? (describe (make-thing "Blue Chair"))
#<COMPILED-LEXICAL-CLOSURE LOCAL-FUNCTION #x2AA3C6E>
Name: LOCAL-FUNCTION
Inner lfun: #<Compiled-function LOCAL-FUNCTION (Non-Global)
#x2A9AFD6>
Closed over values
(0): "Blue Chair"

From the identifier you can see that both closures use the same 'Inner
lfun' #x2A9AFD6.
From the identifier you can see that both closures are different:
#x2AA04BE  and  #x2AA3C6E
The closures list different 'closed over values: "Red Chair" and "Blue
Chair".

Both closures have the same inner function (it is just one function)
but different variable bindings.
So, we have two closures, but only one inner function and two
different bindings.

Do you see the difference to your 'explanation'? It is not sufficient
that a function
has its own (uniquely named) global variables. You would need new
variables
every time a closure gets created.

Let's try your version:

(defparameter __name nil)

(defun make-thing (name)
  (setf __name name)
  (flet ((local-function (message &rest args)
           (case message
             (:print (format t "Hi, I am ~a" __name))
             (:rename (setf __name (first args))))))
     #'local-function))

(let ((a (make-thing :a))
      (b (make-thing :b)))
   (funcall a :print)
   (terpri)
   (funcall b :print))

Hi, I am B
Hi, I am B

Too, bad. Doesn't work. No closures.

? (describe (make-thing :A))
#<Compiled-function LOCAL-FUNCTION (Non-Global)  #x2ADD4D6>
Name: LOCAL-FUNCTION
Arglist (analysis): (CCL::ARG-0 &REST CCL::THE-REST)

Again, no closure.

Above is btw. Common Lisp, which uses lexical binding by default
(different from Emacs Lisp)
and thus supports closures directly.

> --------------

> Note: The terminology “Closure” is actually a very bad terminology. It
> spreads endless confusion and non-understanding. See:

Your usual FUD. If you study the above example, you can end your
confusion.

...


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Edward  
View profile
 More options May 2, 7:19 pm
Newsgroups: comp.lang.lisp
From: Edward <edward.do...@gmail.com>
Date: Fri, 2 May 2008 16:19:56 -0700 (PDT)
Local: Fri, May 2 2008 7:19 pm
Subject: Re: A question (confusion) about closure
On May 2, 1:31 am, Samik <sam...@gmail.com> wrote:

Hi Samik,

I'm no pro,  but Graham's explanation does not square with everything
else I've been learning about closures.  The definitions you provided
are correct,  but they are difficult to understand for people who are
unfamiliar with the terms they use.  The big "aha" moment for me
occurred when I realized the "lexical environment" was a THING.  It's
essentially something like an association table that matches symbols
to values.

Think of it this way:  in a Lisp without closures,  a procedure is
just a procedure.  In a lisp with closures,  a procedure is data-
structure that has two parts:  1) code that does something,  and 2)
something like an association table that captures the state of all the
variables when the function is called.  So every time a function is
run in a Lisp with closures,  a new lexical environment is
manufactured to go along with it.

When Lispers talk about how closures can be used to implement objects
and object-oriented programming,  they are talking about using
techniques to coax the procedure part of the procedure-data-structure
into manipulating the lexical environment part of the procedure-data-
structure.

Edward


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
xahlee@gmail.com  
View profile
(3 users)  More options May 2, 9:07 pm
Newsgroups: comp.lang.lisp
From: "xah...@gmail.com" <xah...@gmail.com>
Date: Fri, 2 May 2008 18:07:31 -0700 (PDT)
Local: Fri, May 2 2008 9:07 pm
Subject: Re: A question (confusion) about closure
Dear joswig,

i don't quite understand what you were saying, perhaps largely due to
your use of Common Lisp and jargons specific to it.

If you would, defend your thesis using plain English with good effort
at technical writing, or perhaps with emacs lisp code, then we can
start a debate.

if you think hard about closures, as if turning the concept into a
mathematical definition (aka formalization or codification), and
further, if you like, take a survey of say the top 10 major langs,
about their concept of closure (if any), further, then i think you'll
agree, that what i said about closures is perfect. Note the word
_perfect_ here. Its not _approximately right_, nor _helpful analogy_,
nor _insightful_. Perfect.

I am perfect.

  Xah
  x...@xahlee.org
http://xahlee.org/


On May 2, 4:11 pm, "jos...@corporate-world.lisp.de" <jos...@corporate-


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
George Neuner  
View profile
 More options May 3, 1:47 am
Newsgroups: comp.lang.lisp
From: George Neuner <gneuner2/@/comcast.net>
Date: Sat, 03 May 2008 01:47:52 -0400
Local: Sat, May 3 2008 1:47 am
Subject: Re: A question (confusion) about closure
On Fri, 2 May 2008 18:07:31 -0700 (PDT), "xah...@gmail.com"

<xah...@gmail.com> wrote:
>Dear joswig,

>i don't quite understand what you were saying, perhaps largely due to
>your use of Common Lisp and jargons specific to it.

Rainer could have explained the concept without resorting to Lisp, but
apart from the lame attempt to relate closures to state, your
explanation was completely useless.

>If you would, defend your thesis using plain English with good effort
>at technical writing, or perhaps with emacs lisp code, then we can
>start a debate.

>if you think hard about closures, as if turning the concept into a
>mathematical definition (aka formalization or codification), and
>further, if you like, take a survey of say the top 10 major langs,
>about their concept of closure (if any), further, then i think you'll
>agree, that what i said about closures is perfect. Note the word
>_perfect_ here. Its not _approximately right_, nor _helpful analogy_,
>nor _insightful_. Perfect.

Your explanation was so off the mark as to be totally meaningless ...
not even just confusing ... totally meaningless.

>I am perfect.

A perfect imbecile maybe.

>  Xah

George