[comp.lang.lisp] CL and lexical closures

ik@vogon.laic.uucp (Ik Su Yoo) (07/26/89)

It seems to me like whenever one uses #'(lambda ...), there is an
overhead because the form must remember its lexical environment.
Although I find these kinds of forms very useful, I still have
questions about their cost:

  1. How much cost is there for using lexical closures?

  2. Is lexical closure always created when using #'(lambda ...), or
     only when there is a free variable access within the form? If the
     former, does it save all bindings?

  3. [related to 2] Which of the following is more efficient?

       (defun store-fn (slot-name)
	 (setf (get slot-name 'lookup-fn)
	       #'(lambda (object)
		   (foo object slot-name))))

       (defun store-fn (slot-name)
	 (setf (get slot-name 'lookup-fn)
	       (eval `(compile nil
			       #'(lambda (object)
				   (foo object ',slot-name))))))

Thanks in advance for any insights.

john@linus.UUCP (John D. Burger) (07/29/89)

Interpreted LAMBDAs will normally result in lexical closures,
even something stupid like

     (LAMBDA () 42)

because there's no simple way to determine that no free variable
access is going on.  On the other hand, any good CL compiler should,
as you say, only create a closure when there is such a free variable
access.  You might think that only the relevant bindings should be
stored, but I think that usually the closure will simply point to the
whole lexical environment.  This is necessary when several closures
share access to free variables, which they can use to communicate.
Pointing to the whole environment can be avoided, but it's somewhat
messy.

As to your two examples, which I took the liberty of changing somewhat:

     (DEFUN STORE-FN-1 (SLOT-NAME)
       (SETF (GET SLOT-NAME 'LOOKUP-FN)
             #'(LAMBDA (OBJECT)
                 (FOO OBJECT SLOT-NAME))))

     (DEFUN STORE-FN-2 (SLOT-NAME)
       (SETF (GET SLOT-NAME 'LOOKUP-FN)
             (COMPILE NIL
                      `(LAMBDA (OBJECT)
                         (FOO OBJECT ',SLOT-NAME)))))

Presumably, you're asking about the efficiency of the two internal
functions, not the relative efficiency of STORE-FN-1 and STORE-FN-2.

On most architectures, the result of STORE-FN-2 should be faster than
STORE-FN-1, because the latter has to do a free variable access, while
the former just pushes a constant onto the stack.

Of course, STORE-FN-2 itself is SLOWER than STORE-FN-1, since it calls
the compiler.







-- 
John Burger                                               john@mitre.org

"You ever think about .signature files? I mean, do we really need them?"
  - alt.andy.rooney

nagle@well.UUCP (John Nagle) (07/29/89)

In article <638@laic.UUCP> ik@.UUCP () writes:
-  3. [related to 2] Which of the following is more efficient?
-
-       (defun store-fn (slot-name)
-	 (setf (get slot-name 'lookup-fn)
-	       #'(lambda (object)
-		   (foo object slot-name))))
-
-       (defun store-fn (slot-name)
-	 (setf (get slot-name 'lookup-fn)
-	       (eval `(compile nil
-			       #'(lambda (object)
-				   (foo object ',slot-name))))))
-
     Since the second will invoke the compiler at run-time, it is highly
undesirable in a production program.  With KCL, this will result in a
delay of a second or more as the compiler is loaded, and this will occur
every time the function is invoked.

					John Nagle