(defun make-it-5 (num)
(setq num 5))
(setq a 0)
(make-it-5 a)
;; now a is still 0, not 5.
In the above code, it seems neither (setq a 5) nor (setq 0 5) happens. If (setq a 5) happened, then a would have changed to 5, but a is still 0. If (setq 0 5) happened, Lisp error would have occurred. What does happen? That is my question.
For some of you who got here by googling and wondering how to make make-it-5 work as its name suggest, one way is
(defmacro make-it-7 (num) ; defmacro instead of defun
`(setq ,num 7))
(setq a 0)
(make-it-7 a)
;; now a is 7.
Another is:
(defun make-it-plus (num-var)
(set num-var (+ 1 (symbol-value num-var))) ; `set' instead of `setq'
)
(setq a 0)
(make-it-plus 'a) ; 'a instead of a
;; now a is 1.
The short answer is that the
(setq num 5)changes the binding fornum, which is a binding local to themake-it-5function.A breakdown follows. It’s good to make sure you’re familiar with the notion of evaluation.
When the
(make-it-5 a)is evaluated, the interpreter looks for a function in the first element of the expression. In this case, the first element is a symbol (make-it-5– which means it is a named function), so it looks in the symbol’s function cell. Note: this lookup can repeat itself, see Symbol Function Indirection.The rest of the elements of the expression are evaluated to find values. In this case, there’s just one symbol (
a), and so the interpreter returns the contents of its value cell, which is0.The interpreter then applies the function to the list of arguments, which involves making local bindings between its arguments to the values passed in. In this case, a local binding between the symbol
numand the value0is made. Then the body of the function is evaluated in that environment.The body is just a single expression which is a “call” to
setq. I put “call” in quotes becausesetqis a special form and doesn’t evaluate its first argument, but looks up the symbol and sets the most local existing binding, which is the binding created inside the functionmake-it-5.So, you’re changing the binding for the symbol
numwhich is local to the functionmake-it-5.