This question is an extension of Common Lisp scoping (dynamic vs lexical)
I have read and (hopefully) understood the concepts of scoping and extent in Common Lisp (link: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node43.html), but I am unable to get my head around the following three examples. All examples are run on a fresh lisp session in SBCL/Slime/Emacs.
Example 1: Prints 5 & 5
(defvar x 100)
(defun fun1 (x)
(print x)
(fun2))
(defun fun2 ()
(print x))
(fun1 5)
Example 2: Prints 5 & 100
(defun fun1 (x)
(print x)
(fun2))
(defun fun2 ()
(print x))
(defvar x 100)
(fun1 5)
Example 3: Prints 5 & 5 & 100
(defvar x 100)
(defun fun1 (x)
(print x)
(fun2))
(defun fun2 ()
(print x))
(defvar x 100)
(fun1 5)
x
I understand why fun1 always prints 5 (due to lexical scope, but please correct if I'm wrong). What I don't understand is why fun2 prints 5 in Example 1, 100 in Example 2 and again 5 in Example 3?
It has something to do with the following extract from Guy Steel's Common Lisp book, but I cannot get my head around it:
"Constructs that use lexical scope effectively generate a new name for each established entity on each execution. Therefore dynamic shadowing cannot occur (though lexical shadowing may). This is of particular importance when dynamic extent is involved."
Is the following statement always true (source: https://courses.engr.illinois.edu/cs421/sp2010/lectures/dynamicscope.pdf):
The binding rule in Lisp is this: a use of a name is bound to the most recent declaration of that name that is still live.
I'm starting to understand some of the parts, but cannot get a wholistic understanding of all three parts, so it would be very helpful if you could help.
Some annotations to your code:
Example 1
(defvar x 100) ; declares X to be special, globally and locally
; also sets X to 100
(defun fun1 (x) ; X is a dynamically bound variable
(print x) ; lookup of dynamic binding of X
(fun2))
(defun fun2 ()
(print x)) ; lookup of dynamic binding of X
(fun1 5)
Example 2
(defun fun1 (x) ; X is a lexical local variable
(print x) ; lexical reference to X
(fun2))
(defun fun2 ()
(print x)) ; X is undeclared/undefined
; the exact behaviour is undefined in Common Lisp
; many implementations assume dynamic lookup of X
; most compilers will show a warning
; CMUCL also by default declared X globally to be special
; -> don't use this in your code
(defvar x 100) ; declares X to be special, globally and locally
; also sets X to 100
(fun1 5)
Example 3
(defvar x 100) ; declares X to be special, globally and locally
; also sets X to 100
(defun fun1 (x) ; X is a dynamically bound variable
(print x) ; lookup of dynamic binding of X
(fun2))
(defun fun2 ()
(print x)) ; lookup of dynamic binding of X
(defvar x 100) ; does nothing
; -> X is already declared special
; -> X already has a value
; see also: DEFPARAMETER
(fun1 5)
x ; lookup of global (or thread local) value of X
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With