what's going on when I setq a parameter variable in a defun? (Emacs)
(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开发者_JAVA技巧 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 for num
, which is a binding local to the make-it-5
function.
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 is 0
.
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 num
and the value 0
is 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 because setq
is 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 function make-it-5
.
So, you're changing the binding for the symbol num
which is local to the function make-it-5
.
精彩评论