GNU Info

Info Node: (cl)Lexical Bindings

(cl)Lexical Bindings


Next: Function Bindings Prev: Dynamic Bindings Up: Variable Bindings
Enter node , (file) or (file)node

Lexical Bindings
----------------

The "CL" package defines the following macro which more closely follows
the Common Lisp `let' form:

 - Special Form: lexical-let (bindings...) forms...
     This form is exactly like `let' except that the bindings it
     establishes are purely lexical.  Lexical bindings are similar to
     local variables in a language like C:  Only the code physically
     within the body of the `lexical-let' (after macro expansion) may
     refer to the bound variables.

          (setq a 5)
          (defun foo (b) (+ a b))
          (let ((a 2)) (foo a))
               => 4
          (lexical-let ((a 2)) (foo a))
               => 7

     In this example, a regular `let' binding of `a' actually makes a
     temporary change to the global variable `a', so `foo' is able to
     see the binding of `a' to 2.  But `lexical-let' actually creates a
     distinct local variable `a' for use within its body, without any
     effect on the global variable of the same name.

     The most important use of lexical bindings is to create "closures".
     A closure is a function object that refers to an outside lexical
     variable.  For example:

          (defun make-adder (n)
            (lexical-let ((n n))
              (function (lambda (m) (+ n m)))))
          (setq add17 (make-adder 17))
          (funcall add17 4)
               => 21

     The call `(make-adder 17)' returns a function object which adds 17
     to its argument.  If `let' had been used instead of `lexical-let',
     the function object would have referred to the global `n', which
     would have been bound to 17 only during the call to `make-adder'
     itself.

          (defun make-counter ()
            (lexical-let ((n 0))
              (function* (lambda (&optional (m 1)) (incf n m)))))
          (setq count-1 (make-counter))
          (funcall count-1 3)
               => 3
          (funcall count-1 14)
               => 17
          (setq count-2 (make-counter))
          (funcall count-2 5)
               => 5
          (funcall count-1 2)
               => 19
          (funcall count-2)
               => 6

     Here we see that each call to `make-counter' creates a distinct
     local variable `n', which serves as a private counter for the
     function object that is returned.

     Closed-over lexical variables persist until the last reference to
     them goes away, just like all other Lisp objects.  For example,
     `count-2' refers to a function object which refers to an instance
     of the variable `n'; this is the only reference to that variable,
     so after `(setq count-2 nil)' the garbage collector would be able
     to delete this instance of `n'.  Of course, if a `lexical-let'
     does not actually create any closures, then the lexical variables
     are free as soon as the `lexical-let' returns.

     Many closures are used only during the extent of the bindings they
     refer to; these are known as "downward funargs" in Lisp parlance.
     When a closure is used in this way, regular Emacs Lisp dynamic
     bindings suffice and will be more efficient than `lexical-let'
     closures:

          (defun add-to-list (x list)
            (mapcar (lambda (y) (+ x y))) list)
          (add-to-list 7 '(1 2 5))
               => (8 9 12)

     Since this lambda is only used while `x' is still bound, it is not
     necessary to make a true closure out of it.

     You can use `defun' or `flet' inside a `lexical-let' to create a
     named closure.  If several closures are created in the body of a
     single `lexical-let', they all close over the same instance of the
     lexical variable.

     The `lexical-let' form is an extension to Common Lisp.  In true
     Common Lisp, all bindings are lexical unless declared otherwise.

 - Special Form: lexical-let* (bindings...) forms...
     This form is just like `lexical-let', except that the bindings are
     made sequentially in the manner of `let*'.


automatically generated by info2www version 1.2.2.9