ToC | DocOverview | CGDoc | RelNotes | Index | PermutedIndex
| Allegro CL

| ANSI Common Lisp 3 Evaluation and Compilation 3.1 Evaluation ### 3.1.5 Shadowing If two forms that establish lexical bindings with the same name N are textually nested, then references to N within the inner form refer to the binding established by the inner form; the inner binding for N shadows the outer binding for N. Outside the inner form but inside the outer one, references to N refer to the binding established by the outer form. For example:
     (defun test (x z)
       (let ((z (* x 2)))
         (print z))
       z)
The binding of the variable `z` by let shadows the parameter binding for the function `test`. The reference to the variable `z` in the print form refers to the let binding. The reference to `z` at the end of the function `test` refers to the parameter named `z`. Constructs that are lexically scoped act as if new names were generated for each object on each execution. Therefore, dynamic shadowing cannot occur. For example:
     (defun contorted-example (f g x)
       (if (= x 0)
           (funcall f)
           (block here
              (+ 5 (contorted-example g
                                      #'(lambda () (return-from here 4))
                                      (- x 1))))))
Consider the call `(contorted-example nil nil 2)`. This produces `4`. During the course of execution, there are three calls to `contorted-example`, interleaved with two blocks:
     (contorted-example nil nil 2)
       (block here1 ...)
         (contorted-example nil #'(lambda () (return-from here1 4)) 1)
           (block here2 ...)
             (contorted-example #'(lambda () (return-from here1 4))
                                #'(lambda () (return-from here2 4))
                                0)
                 (funcall f)
                        where f  #'(lambda () (return-from here1 4))
                     (return-from here1 4)
At the time the `funcall` is executed there are two block exit points outstanding, each apparently named `here`. The return-from form executed as a result of the `funcall` operation refers to the outer outstanding exit point (here1), not the inner one (here2). It refers to that exit point textually visible at the point of execution of function (here abbreviated by the `#'` syntax) that resulted in creation of the function object actually invoked by funcall. If, in this example, one were to change the `(funcall f)` to `(funcall g)`, then the value of the call `(contorted-example nil nil 2)` would be `9`. The value would change because funcall would cause the execution of `(return-from here2 4)`, thereby causing a return from the inner exit point (here2). When that occurs, the value `4` is returned from the middle invocation of `contorted-example`, `5` is added to that to get `9`, and that value is returned from the outer block and the outermost call to `contorted-example`. The point is that the choice of exit point returned from has nothing to do with its being innermost or outermost; rather, it depends on the lexical environment that is packaged up with a lambda expression when function is executed.

© Franz Inc. All Rights Reserved - File last updated 2022-07-25