当我在defun中设置参数变量时会发生什么? (Emacs的)

时间:2011-01-26 19:01:14

标签: function emacs parameters elisp

(defun make-it-5 (num)
  (setq num 5))
(setq a 0)
(make-it-5 a)
;; now a is still 0, not 5.

在上面的代码中,似乎既没有(setq a 5)也没有(setq 0 5)。如果(setq a 5)发生,则a将更改为5,但a仍为0.如果(setq 0 5)发生,则会发生Lisp错误。怎么了?这是我的问题。

对于一些通过谷歌搜索来到这里的人并想知道如何使make-it-5正如其名称所示,其中一种方法是

(defmacro make-it-7 (num) ; defmacro instead of defun
  `(setq ,num 7))
(setq a 0)
(make-it-7 a)
;; now a is 7.

另一个是:

(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.

1 个答案:

答案 0 :(得分:7)

简短回答是(setq num 5) changes the binding for num,它是make-it-5函数的本地绑定。

细分如下。确保您熟悉evaluation的概念是很好的。

当评估(make-it-5 a)时,解释器在表达式的第一个元素中查找函数。在这种情况下,第一个元素是符号(make-it-5 - 这意味着它是named function),因此它在符号的function cell中查找。注意:此查找可以重复,请参阅Symbol Function Indirection

评估表达式的其余元素以查找值。在这种情况下,只有一个符号(a),因此解释器返回the contents of its value cell,即0

然后,解释器将该函数应用于参数列表,其中包括创建local bindings between its arguments to the values passed in。在这种情况下,会在符号num和值0之间生成local binding。然后在该环境中评估函数体。

正文只是一个表达式,是setq的“召唤”。我在引号中加上“call”,因为setqspecial form并且没有评估它的第一个参数,但是查找符号并设置most local existing binding,这是在{}内创建的绑定函数make-it-5

因此,您正在更改函数num的本地符号make-it-5的绑定。