next up previous contents
Next: 5.6.3 Closures Up: 5.6 Local Call Previous: Self-Recursive Calls

5.6.2 Let Calls

  Because local call avoids unnecessary call overheads, the compiler internally uses local call to implement some macros and special forms that are not normally thought of as involving a function call. For example, this let:

(let ((a (foo))
      (b (bar)))
  ...)
is internally represented as though it was macroexpanded into:
(funcall #'(lambda (a b)
             ...)
         (foo)
         (bar))
This implementation is acceptable because the simple cases of local call (equivalent to a let) result in good code. This doesn't make let any more efficient, but does make local calls that are semantically the same as let much more efficient than full calls. For example, these definitions are all the same as far as the compiler is concerned:
(defun foo ()
  ...some other stuff...
  (let ((a something))
    ...some stuff...))

(defun foo () (flet ((localfun (a) ...some stuff...)) ...some other stuff... (localfun something)))

(defun foo () (let ((funvar #'(lambda (a) ...some stuff...))) ...some other stuff... (funcall funvar something)))

Although local call is most efficient when the function is called only once, a call doesn't have to be equivalent to a let to be more efficient than full call. All local calls avoid the overhead of argument count checking and keyword argument parsing, and there are a number of other advantages that apply in many common situations. See section 5.4.1 for a discussion of the optimizations done on let calls.



Raymond Toy
Mon Jul 14 09:11:27 EDT 1997