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

Yoo*_*Yoo 1 parameters emacs elisp function

(defun make-it-5 (num)
  (setq num 5))
(setq a 0)
(make-it-5 a)
;; now a is still 0, not 5.
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,似乎既没有(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.
Run Code Online (Sandbox Code Playgroud)

另一个是:

(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.
Run Code Online (Sandbox Code Playgroud)

Tre*_*son 7

简短的回答是(setq num 5) 更改绑定 num,这是make-it-5函数的本地绑定.

细分如下.确保您熟悉评估的概念是很好的.

(make-it-5 a)评估时,解释器在表达式的第一个元素中查找函数.在这种情况下,第一个元素是一个符号(make-it-5- 这意味着它是一个 命名函数),因此它在符号的函数单元格中查找.注意:此查找可以重复,请参阅符号函数间接.

表达式的其余元素将被评估以查找值.在这种情况下,只有一个符号(a),因此解释器返回其值单元格的内容,即0.

然后,解释器将该函数应用于参数列表,这涉及在传入的值的参数之间进行本地绑定.在这种情况下,进行符号和值之间的本地绑定.然后在该环境中评估函数体.num0

身体只是一个表达,是一个"呼唤" setq.我将"call"放在引号中,因为它setq是一个特殊的形式,不会评估它的第一个参数,但会查找符号并设置最本地的现有绑定,即在函数内创建的绑定make-it-5.

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