Higher order programming with Lisp: Passing a function to mapcar? - lisp

I'm just learning ANSI Common Lisp (using clisp on a Win32 machine) and I was wondering if mapcar could use a function passed in as a formal argument? Please see the following:
(defun foo (fn seq)
(mapcar #'fn seq))
This would, in my opinion, provide a greater level of flexibility than:
(defun mult (i)
(* i 2))
(defun foo ()
(mapcar #'mult '(1 2 3)))

This is absolutely possible! You're almost there. You just bumped into Common Lisp's dual namespaces, which can take a lot of getting used to. I hope I can say a thing or two to make Common Lisp's two namespaces a bit less confusing.
Your code is almost correct. You wrote:
(defun foo (fn seq)
(mapcar #'fn seq))
But, what is that trying to do? Well, #' is shorthand. I'll expand it out for you.
(defun foo (fn seq)
(mapcar (function fn) seq))
So, #'symbol is shorthand for (function symbol). In Common Lisp -- as you seem to know -- symbols can be bound to a function and to a variable; these are the two namespaces that Lispers talk so much about: the function namespace, and the variable namespace.
Now, what the function special form does is get the function bound to a symbol, or, if you like, the value that the symbol has in the function namespace.
Now, on the REPL, what you wrote would be obviously what you want.
(mapcar #'car sequence)
Would map the car function to a sequence of lists. And the car symbol has no variable binding, only a function binding, which is why you need to use (function ...) (or its shorthand, #') to get at the actual function.
Your foo function doesn't work because the function you pass it as an argument is being bound to a symbol as a variable. Try this:
(let ((fn #'sqrt))
(mapcar #'fn '(4 9 16 25)))
You might have expected a list of all those numbers' square roots, but it didn't work. That's because you used let to bind the square root function to fn as a variable. Now, try this code:
(let ((fn #'sqrt))
(mapcar fn '(4 9 16 25)))
Delightful! This binds the square root function to the fn symbol as a variable.
So, let's go revise your foo function:
(defun foo (fn seq)
(mapcar fn seq))
That will work, because fn is a variable. Let's test it, just to make sure:
;; This will not work
(foo sqrt '(4 9 16 25))
;; This will work
(foo #'sqrt '(4 9 16 25))
The first one didn't work, because the square root function is bound to sqrt in the function namespace. So, in the second one, we grabbed the function from the symbol, and passed it to foo, which bound it to the symbol fn as a variable.
Okay, so what if you want to bind a function to a symbol in the function namespace? Well, for starters, defun does that, permanently. If you want it to be temporary, like a let binding, use flet. Flet is, in my opinion, stupid, because it doesn't work exactly like let does. But, I'll give an example, just so you can see.
(flet ((fn (x) (sqrt x)))
(mapcar fn '(4 9 16 25)))
will not work, because flet didn't bind the function to the symbol in the variable namespace, but in the function namespace.
(flet ((fn (x) (sqrt x)))
(mapcar #'fn '(4 9 16 25)))
This will do what you expect, because flet bound that function to the symbol fn in the function namespace. And, just to drive the idea of the function namespace home:
(flet ((fn (x) (sqrt x)))
(fn 16))
Will return 4.

Sure, you can do this:
(defun foo (fn)
(mapcar fn '(1 2 3)))
Examples:
(foo #'(lambda (x) (* x 2)))
(foo #'1+)
(foo #'sqrt)
(foo #'(lambda (x) (1+ (* x 3))))

Related

How is sharp quote (#') different from symbol-function?

To me these operators seem to do the same thing. Both take a symbol and return the function associated with it. Is there any difference?
elisp evaluation returns the following:
(defun foo (x) (+ 1 x))
foo
(foo 3)
4
#'foo
Which I don't understand either.
Furthermore is there a difference between common lisp and elisp? I'm learning from resources on either.
Common Lisp:
SYMBOL-FUNCTION can't retrieve functions from lexically bound functions. FUNCTION references the lexically bound function by default. #'foo is just a shorter notation for (FUNCTION foo).
CL-USER 1 > (defun foo () 'foo)
FOO
CL-USER 2 > (flet ((foo () 'bar))
(list (funcall (symbol-function 'foo))
(funcall #'foo)
(funcall (function foo))
(eq (function foo) (symbol-function 'foo))))
(FOO BAR BAR NIL)
CL-USER 3 > (eq (function foo) (symbol-function 'foo))
T
Rainer's answer discusses the things that you can do with function that you can't do with symbol-function, namely retrieve the value of lexically scoped functions, but there are a few other differences too.
The special operator FUNCTION
The special operator FUNCTION provides a way to find the functional value of a name in a lexical environment. Its argument is either a function name or a lambda expression. That function can take a lambda expression means that you can write: (function (lambda (x) (list x x))). The term function name includes more than just symbols. It also includes lists of the form (setf name), which means that you can do things like (function (setf car)).
The accessor SYMBOL-FUNCTION
The accessor symbol-function, on the other hand, lets you retrieve and set the functional value of a symbol. Since it requires a symbol, you can't do (symbol-function (lambda …)) or (function (setf name)). Symbol-function also can't see lexical environments; it only works with global definitions. E.g.,
(flet ((foo () 'result))
(symbol-function 'foo))
;=> NIL
Since symbol-function is an accessor, you can change the value of a function's symbol with it. E.g.:
CL-USER> (setf (symbol-function 'foo) (lambda () 42))
#<FUNCTION (LAMBDA ()) {1005D29AAB}>
CL-USER> (foo)
42
CL-USER> (setf (symbol-function 'foo) (lambda () 26))
#<FUNCTION (LAMBDA ()) {1005D75B9B}>
CL-USER> (foo)
26
The accessor FDEFINITION
There's also the accessor fdefinition which is kind of like symbol-function in that is can only access globally defined functions, but kind of like function in that it can access of symbols and (setf name) lists. However, it does not retrieve the value of lambda functions.

Unquoting without eval

I store some macros in quoted form (because in fact they produce lambdas with tricky lexical environment and I prefer store and serialize them as lists). So now I'm trying:
(defun play (s)
(funcall (macroexpand s)))
Macroexpand evaluates quoted lambda, so funcall can't run it. How to unquote result of macroexpand without eval? Because in my case it would cause indefensible security hole.
MORE INFO:
What I get look like this (in simplest case):
FUNCALL: #1=#'(LAMBDA (#:G6008) (SYMBOL-MACROLET NIL T)) is not a function name; try using a symbol instead
and symbol-macrolet is what actually builds up "tricky lexical environment" inside lambda.
Macroexpand evaluates quoted lambda, so funcall can't run it. How to
unquote result of macroexpand without eval? Because in my case it
would cause indefensible security hole.
I think that Sylwester's comment about the XY problem is probably right here; it sounds like you're trying to do something that might be done better in a different way. That said, if you have a list that's a lambda expression, you can use coerce to get a function object instead of using eval. That is, you can do this:
CL-USER> (funcall '(lambda () 42))
; Error, like you've been having
CL-USER> (funcall (coerce '(lambda () 42) 'function))
42 ; turned the list (lambda () 42) into a function and called it
This is described in the documentation for coerce; when the "output" type is function, this is what happens with the object argument:
If the result-type is function, and object is any function name that
is fbound but that is globally defined neither as a macro name nor as
a special operator, then the result is the functional value of object.
If the result-type is function, and object is a lambda expression,
then the result is a closure of object in the null lexical
environment.
Thus, if you have a function that returns list of the form (lambda ...), you can use coerce and funcall with its result. This includes macroexpansions, although you may want to use macroexpand-1 rather than macroexpand, because lambda is already a macro, so if you expand too far, (lambda () ...) turns into (function (lambda () ...)).
CL-USER> (defmacro my-constantly (value)
`(lambda () ,value))
MY-CONSTANTLY
CL-USER> (macroexpand-1 '(my-constantly 36))
(LAMBDA () 36)
T
CL-USER> (funcall (coerce (macroexpand-1 '(my-constantly 36)) 'function))
36
If you try that with the plain macroexpand, though, there's a problem. Consider yourself warned:
CL-USER> (macroexpand '(my-constantly 36))
#'(LAMBDA () 36) ; not a list, but a function
T
CL-USER> (funcall (coerce (macroexpand '(my-constantly 36)) 'function))
; Error. :(
I think this is a case where you will find that the REPL is your friend. To get you started:
cl-user> (defmacro foo () #'(lambda () :hi))
foo
cl-user> (foo)
#<Compiled-function (:internal foo) (Non-Global) #x3020014F82FF>
cl-user> (funcall *)
:hi
cl-user> (macroexpand '(foo))
#<Compiled-function (:internal foo) (Non-Global) #x3020014F82FF>
t
cl-user> (funcall *)
:hi
cl-user>
I'll note in passing that the lambda form that appears in your example takes an argument, while your funcall doesn't provide one.
There are several issues with this. First I think this is a XY problem so if you show more of your problem I guess we might find a solution for it.
It has nothing with unquoting since when evaluation a quoted expression it's not longer quoted, but it's turn into data representation of the original quoted expression. You must eval data if you want to run it.
With eval you won't get the current lexical scope. So since you mention eval and lexical environment in the same post makes me thing you won't get what you want.
Now it's no problem making a list of functions, like this:
(list (lambda (x) (+ x x))
This is not quoted since I use list and teh lambda is evaluated to a closure. If it was assigned to variable x you could call it with (funcall (car x) 10)) ; ==> 20
EDIT
I actually made the same error message with this code:
(defmacro test () '#'(lambda (x) x))
(macroexpand '(test)) ; ==> #'(lambda (x) x) ; t
(funcall (macroexpand '(test)) 5) ; ==>
*** - funcall: #'(lambda (x) x) is not a function name; try using a symbol
instead
It doesn't work since you cannot call a lambda unevaluated. You need to call the closure (function) which is the result of the evaluation of the lambda form. If you would instead not quote it you'll have that evaluation in the macro:
(defmacro test () #'(lambda (x) x))
(macroexpand '(test)) ; ==> #<function :lambda (x) x> ;
(funcall (macroexpand '(test)) 5) ; ==> 5
Actually I cannot see why you would need to make this a macro. Lets make it a function instead.
(defun test () #'(lambda (x) x))
(funcall (test) 5 ) ; ==> 5
Even if this was more comples in most cases you would do with a closure.

Still about quote in Lisp

I am a novice in Lisp, learning slowly at spare time... Months ago, I was puzzled by the error report from a Lisp REPL that the following expression does not work:
((if (> 2 1) + -) 1 2)
By looking around then I knew that Lisp is not Scheme...in Lisp, I need to do either:
(funcall (if (> 2 1) '+ '-) 2 1), or
(funcall (if (> 2 1) #'+ #'-) 2 1)
I also took a glimpse of introductary material about lisp-1 and lisp-2, although I was not able to absort the whole stuff there...in any case, I knew that quote prevents evaluation, as an exception to the evaluation rule.
Recently I am reading something about reduce...and then as an exercise, I wanted to write my own version of reduce. Although I managed to get it work (at least it seems working), I realized that I still cannot exactly explain why, in the body of defun, that some places funcall is needed, and at some places not.
The following is myreduce in elisp:
(defun myreduce (fn v lst)
(cond ((null lst) v)
((atom lst) (funcall fn v lst))
(t (funcall fn (car lst) (myreduce fn v (cdr lst))))))
(myreduce '+ 0 '(1 2 3 4))
My questions are about the 3rd and 4th lines:
The 3rd line: why I need funcall? why not just (fn v lst)? My "argument" is that in (fn v lst), fn is the first element in the list, so lisp may be able to use this position information to treat it as a function...but it's not. So certainly I missed something here.
The 4th line in the recursive call of myreduce: what kind of fn be passed to the recursive call to myreduce? '+ or +, or something else?
I guess there should be something very fundamental I am not aware of...I wanted to know, when I call myreduce as shown in the 6th/last line, what is exactly happening afterwards (at least on how the '+ is passed around), and is there a way to trace that in any REPL environment?
Thanks a lot,
/bruin
Common Lisp is a LISP-2 and has two namespaces. One for functions and one for variables. Arguments are bound in the variable namespace so fn does not exist in the function namespace.
(fn arg) ; call what fn is in the function namespace
(funcall fn ...) ; call a function referenced as a variable
'+ is a symbol and funcall and apply will look it up in the global function namespace when it sees it's a symbol instead of a function object. #'+ is an abbreviation for (function +) which resolves the function from the local function namespace. With lots of calls #'+ is faster than '+ since '+ needs a lookup. Both symbol and a function can be passed as fn to myreduce and whatever was passed is the same that gets passed in line 4.
(myreduce '+ 0 '(1 2 3 4)) ; here funcall might lookup what '+ is every time (CLISP does it while SBLC caches it)
(myreduce #'+ 0 '(1 2 3 4)); here funcall will be given a function object looked up in the first call in all consecutive calls
Now if you pass '+ it will be evaluated to + and bound to fn.
In myreduce we pass fn in the recursion and it will be evaluated to + too.
For #'+ it evaluates to the function and bound to fn.
In myreduce we pass fn in the recursion and it will be evaluated to the function object fn was bound to in the variable namespace.
Common Lisp has construct to add to the function namespace. Eg.
(flet ((double (x) (+ x x))) ; make double in the function namespace
(double 10)) ; ==> 20
But you could have written it and used it on the variable namespace:
(let ((double #'(lambda (x) (+ x x)))) ; make double in the variable namespace
(funcall double 10))
Common Lisp has two (actually more than two) namespaces: one for variables and one for functions. This means that one name can mean different things depending on the context: it can be a variable and it can be a function name.
(let ((foo 42)) ; a variable FOO
(flet ((foo (n) (+ n 107))) ; a function FOO
(foo foo))) ; calling function FOO with the value of the variable FOO
Some examples how variables are defined:
(defun foo (n) ...) ; n is a variable
(let ((n 3)) ...) ; n is a variable
(defparameter *n* 41) ; *n* is a variable
So whenever a variable is defined and used, the name is in the variable namespace.
Functions are defined:
(defun foo (n) ...) ; FOO is a function
(flet ((foo (n) ...)) ...) ; FOO is a function
So whenever a function is defined and used, the name is in the function namespace.
Since the function itself is an object, you can have function being a variable value. If you want to call such a value, then you need to use FUNCALL or APPLY.
(let ((plus (function plus)))
(funcall plus 10 11))
Now why are things like they are? ;-)
two namespaces allow us to use names as variables which are already functions.
Example: in a Lisp-1 I can't write:
(defun list-me (list) (list list))
In Common Lisp there is no conflict for above code.
a separate function namespace makes compiled code a bit simpler:
In a call (foo 42) the name FOO can only be undefined or it is a function. Another alternative does not exist. So at runtime we never have to check the function value of FOO for actually being a function object. If FOO has a function value, then it must be a function object. The reason for that: it is not possible in Common Lisp to define a function with something other than a function.
In Scheme you can write:
(let ((list 42))
(list 1 2 3 list))
Above needs to be checked at some point and will result in an error, since LIST is 42, which is not a function.
In Common Lisp above code defines only a variable LIST, but the function LIST is still available.

Higher Order Function Syntax in Common Lisp

I'm teaching myself Common Lisp using Norvig's Paradigms of AI Programming and came across something I didn't understand and he didn't explain.
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
What is the difference between calling a higher order function as follows, higherOrderFunc #'funcName funcArg and what he does when calling mapcar without #'? Is #' necessary when calling a higher order function?
Common Lisp has different namespaces for functions and variables.
(defun mappend (fn the-list)
(apply #'append (mapcar fn the-list)))
Above MAPPEND gets defined with two local variables fn and the-list
APPLY gets passed the function value of APPEND.
MAPCAR gets passed the variable value of FN.
Similar see this:
CL-USER 129 > (flet ((add-something (number)
(+ number 17)))
(let ((add-something (lambda (number)
(+ number 42))))
(list
(mapcar #'add-something '(1 2 3))
(mapcar add-something '(1 2 3)))))
->
((18 19 20) (43 44 45))
LET creates local variables, FLET creates local functions.
The first mapcar uses the function namespace and the second uses the variable namespace.
Common Lisp uses a special function namespace because it was thought to be more efficient (slightly easier to implement a fast Lisp) and to allow functions and variables to have the same name.
In Common Lisp we can write:
(defun list-me (list)
(list list))
In Scheme, which does not have separate namespaces one would write something like this:
(define (list-me lst)
(list lst))
#' is syntactic sugar for function: #'foo is read as (function foo).
Function is a special operator that returns the function value bound to the name given. If you pass a function as a parameter, that parameter (in your case, fn) has its value bound to the function. To pass it on to another function, you can simply put the variable name into the call form. However, to get the function value of a name, you need to access it with function.
Using #' is not strictly required. If instead you simply pass 'foo the symbol-function will be invoked. Consider the following:
* (defvar foo #'(lambda (a) 'var))
* (setf (symbol-function 'foo) #'(lambda (a) 'fun))
* (mapcar 'foo '(a b))
(FUN FUN)
* (mapcar #'foo '(a b))
(FUN FUN)
* (mapcar foo '(a b))
(VAR VAR)
Practially #'foo or 'foo are equivalent:
X3J13 voted [...] to allow the 'function' to the only of type 'symbol'
or 'function'; [...] one must use the 'function' special form [...]
before a lambda-expression [...].
Specification of the function in flet has some interesting properties:
* (flet ((foo (a) 'FLET))
(mapcar foo '(a b))) ; Uses 'value' of foo
(VAR VAR)
* (flet ((foo (a) 'FLET))
(mapcar 'foo '(a b))) ; Uses 'function' of foo
(FUN FUN)
* (flet ((foo (a) 'FLET))
(mapcar #'foo '(a b))) ; Uses local binding 'flet' of foo
(FLET FLET)

Dynamic and Lexical variables in Common Lisp

I am reading the book 'Practical Common Lisp' by Peter Seibel.
In Chapter 6, "Variables" sections
"Lexical Variables and Closures" and "Dynamic, a.k.a. Special, Variables".
http://www.gigamonkeys.com/book/variables.html
My problem is that the examples in both sections show how (let ...) can shadow global variables and doesn't really tell the difference between the Dynamic and Lexical vars.
I understand how closures work but I don't really get whats so special about let in this example:
(defvar *x* 10)
(defun foo ()
(format t "Before assignment~18tX: ~d~%" *x*)
(setf *x* (+ 1 *x*))
(format t "After assignment~18tX: ~d~%" *x*))
(defun bar ()
(foo)
(let ((*x* 20)) (foo))
(foo))
CL-USER> (foo)
Before assignment X: 10
After assignment X: 11
NIL
CL-USER> (bar)
Before assignment X: 11
After assignment X: 12
Before assignment X: 20
After assignment X: 21
Before assignment X: 12
After assignment X: 13
NIL
I feel like there is nothing special is going on here. The outer foo in bar increments the global x, and foo surrounded by let in bar increments the shadowed x. What's the big deal? I don't see how is this supposed to explain the difference between lexical and dynamic variables. Yet the book continues like this:
So how does this work? How does LET
know that when it binds x it's
supposed to create a dynamic binding
rather than a normal lexical binding?
It knows because the name has been
declared special.12 The name of every
variable defined with DEFVAR and
DEFPARAMETER is automatically declared
globally special.
What would happen if let would bind x using "normal lexical binding"? All in all, what are the differences between dynamic and lexical binding and how is this example special regarding dynamic binding?
What's going on?
You say: feel like there is nothing special is going on here. The outer foo in bar increments the global x, and foo surrounded by let in bar increments the shadowed x. What's the big deal?
The special that's going on here is that LET can shadow the value of *x*. With lexical variables that's not possible.
The code declares *x* to be special via the DEFVAR.
In FOO now the value of *x* is looked up dynamic. FOO will take the current dynamic binding of *x* or, if there is none, the symbol value of the symbol *x*. A new dynamic binding can, for example, be introduced with LET.
A lexical variable on the other hand has to be present in the lexical environment somewhere. LET, LAMBDA, DEFUN and others can introduce such lexical variables. See here the lexical variable x introduced in three different ways:
(let ((x 3))
(* (sin x) (cos x)))
(lambda (x)
(* (sin x) (cos x)))
(defun baz (x)
(* (sin x) (cos x)))
If our code were:
(defvar x 0)
(let ((x 3))
(* (sin x) (cos x)))
(lambda (x)
(* (sin x) (cos x)))
(defun baz (x)
(* (sin x) (cos x)))
Then X were special in all three above cases, because of the DEFVAR declaration, which declares X to be special - globally for all levels. Because of this, there is the convention to declare special variables as *X*. Thus only variables with stars around them are special - by convention. That's a useful convention.
In your code you have then:
(defun bar ()
(foo)
(let ((*x* 20))
(foo))
(foo))
Since *x* has be declared special via the DEFVAR above in your code, the LET construct introduces a new dynamic binding for *x*. FOO is then called. Since inside FOO the *x* uses dynamic binding, it looks up the current one and finds that *x* is dynamically bound to 20.
The value of a special variable is found in the current dynamic binding.
Local SPECIAL declarations
There are also local special declarations:
(defun foo-s ()
(declare (special *x*))
(+ *x* 1))
If the variable had been declared special by a DEFVAR or DEFPARAMETER, then the local special declaration can be omitted.
A lexical variable directly references the variable binding:
(defun foo-l (x)
(+ x 1))
Let's see it in practice:
(let ((f (let ((x 10))
(lambda ()
(setq x (+ x 1))))))
(print (funcall f)) ; form 1
(let ((x 20)) ; form 2
(print (funcall f))))
Here all variables are lexical. In form 2 the LET will not shadow the X in our function f. It can't. The function uses the lexical bound variable, introduced by the LET ((X 10). Surrounding the call with another lexically bound X in form 2 has no effect on our function.
Let's try special variables:
(let ((f (let ((x 10))
(declare (special x))
(lambda ()
(setq x (+ x 1))))))
(print (funcall f)) ; form 1
(let ((x 20)) ; form 2
(declare (special x))
(print (funcall f))))
What now? Does that work?
It does not!
The first form calls the function and it tries to look up the dynamic value of X and there is none. We get an error in form 1: X is unbound, because there is no dynamic binding in effect.
Form 2 would work, since the LET with the special declaration introduces a dynamic binding for X.
When a variable is lexically scoped, the system looks to where the function is defined to find the value for a free variable. When a variable is dynamically scoped, the system looks to where the function is called to find the value for the free variable. Variables in Common Lisp are all lexical by default; however, dynamically scoped variables can be defined at the top level using defvar or defparameter.
A simpler example
lexical scoping (with setq):
(setq x 3)
(defun foo () x)
(let ((x 4)) (foo)) ; returns 3
dynamic scoping (with defvar):
(defvar x 3)
(defun foo () x)
(let ((x 4)) (foo)) ; returns 4
How does the let know if a variable is lexical or dynamic? It doesn't. On the other hand, when foo goes to find the value of X, it will initially find the lexical value defined at the top level. It then checks to see if the variable is supposed to be dynamic. If it is, then foo looks to the calling environment, which, in this case, uses let to overshadow the value of X to be 4.
(note: this is an oversimplification, but it will help to visualize the difference between the different scoping rules)
Maybe this example will help.
;; the lexical version
(let ((x 10))
(defun lex-foo ()
(format t "Before assignment~18tX: ~d~%" x)
(setf x (+ 1 x))
(format t "After assignment~18tX: ~d~%" x)))
(defun lex-bar ()
(lex-foo)
(let ((x 20)) ;; does not do anything
(lex-foo))
(lex-foo))
;; CL-USER> (lex-bar)
;; Before assignment X: 10
;; After assignment X: 11
;; Before assignment X: 11
;; After assignment X: 12
;; Before assignment X: 12
;; After assignment X: 13
;; the dynamic version
(defvar *x* 10)
(defun dyn-foo ()
(format t "Before assignment~18tX: ~d~%" *x*)
(setf *x* (+ 1 *x*))
(format t "After assignment~18tX: ~d~%" *x*))
(defun dyn-bar()
(dyn-foo)
(let ((*x* 20))
(dyn-foo))
(dyn-foo))
;; CL-USER> (dyn-bar)
;; Before assignment X: 10
;; After assignment X: 11
;; Before assignment X: 20
;; After assignment X: 21
;; Before assignment X: 11
;; After assignment X: 12
;; the special version
(defun special-foo ()
(declare (special *y*))
(format t "Before assignment~18tX: ~d~%" *y*)
(setf *y* (+ 1 *y*))
(format t "After assignment~18tX: ~d~%" *y*))
(defun special-bar ()
(let ((*y* 10))
(declare (special *y*))
(special-foo)
(let ((*y* 20))
(declare (special *y*))
(special-foo))
(special-foo)))
;; CL-USER> (special-bar)
;; Before assignment X: 10
;; After assignment X: 11
;; Before assignment X: 20
;; After assignment X: 21
;; Before assignment X: 11
;; After assignment X: 12
You can tell your Lisp to bind local variables dynamically, too:
(let ((dyn 5))
(declare (special dyn))
... ;; DYN has dynamic scope for the duration of the body
)
Rewrite example from PCL.
;;; Common Lisp is lexically scoped by default.
λ (setq x 10)
=> 10
λ (defun foo ()
(setf x (1+ x)))
=> FOO
λ (foo)
=> 11
λ (let ((x 20))
(foo))
=> 12
λ (proclaim '(special x))
=> NIL
λ (let ((x 20))
(foo))
=> 21
Yet another great explanation from On Lisp, chapter 2.5 Scope:
Common Lisp is a lexically scoped Lisp. Scheme is the oldest dialect with lexical scope; before Scheme, dynamic scope was considered one of the defining features of Lisp.
The difference between lexical and dynamic scope comes down to how an implementation deals with free variables. A symbol is bound in an expression if it has been established as a variable, either by appearing as a parameter, or by variable-binding operators like let and do. Symbols which are not bound are said to be free. In this example, scope comes into play:
(let ((y 7))
(defun scope-test (x)
(list x y)))
Within the defun expression, x is bound and y is free. Free variables are interesting because it’s not obvious what their values should be. There’s no uncertainty about the value of a bound variable—when scope-test is called, the value of x should be whatever is passed as the argument. But what should be the value of y? This is the question answered by the dialect’s scope rules.
In a dynamically scoped Lisp, to find the value of a free variable when exe- cuting scope-test, we look back through the chain of functions that called it. When we find an environment where y was bound, that binding of y will be the one used in scope-test. If we find none, we take the global value of y. Thus, in a dynamically scoped Lisp, y would have the value it had in the calling expression:
> (let ((y 5)) (scope-test 3))
(3 5)
With dynamic scope, it means nothing that y was bound to 7 when scope-test was defined. All that matters is that y had a value of 5 when scope-test was called.
In a lexically scoped Lisp, instead of looking back through the chain of calling functions, we look back through the containing environments at the time the function was defined. In a lexically scoped Lisp, our example would catch the binding of y where scope-test was defined. So this is what would happen in Common Lisp:
> (let ((y 5)) (scope-test 3))
(3 7)
Here the binding of y to 5 at the time of the call has no effect on the returned value.
Though you can still get dynamic scope by declaring a variable to be special, lexical scope is the default in Common Lisp. On the whole, the Lisp community seems to view the passing of dynamic scope with little regret. For one thing, it used to lead to horribly elusive bugs. But lexical scope is more than a way of avoiding bugs. As the next section will show, it also makes possible some new programming techniques.