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