了解给定代码中的变量范围

Understanding variable scope in given code

我是 Emacs lisp 的初学者,所以这确实是一个菜鸟问题。假设我必须编写一个函数,该函数使用循环将数字向量的每个元素加 1。

这是我写的代码(注释表明我在每一步尝试做什么):

(defun add-one (x)
  "Use a loop to add 1 to each element of list X"
  (let* ((res x) ; make a copy of X
         (counter 0)) ; set counter to 0
    (while (< counter (length x))
      ;; Replace each element of RES by adding 1:
      (setcar (nthcdr counter res) (1+ (car (nthcdr counter x))))
      (setq counter (1+ counter)))
    ;; Display result:
    (message "%s" res)))

但我的代码似乎对 x 具有破坏性,因为对该函数的多次调用不会产生相同的结果:

;; Define a list:
(setq mylist '(1 2 3 4))
;; Several calls to the function:
(add-one mylist) ; -> (2 3 4 5)
(add-one mylist) ; -> (3 4 5 6)

这是我的问题:我不明白为什么我的代码具有破坏性(我预计每次执行的结果都是 (2 3 4 5))。我知道 setcar 具有破坏性,但它应用于 x 的副本,而不是 x 本身。那为什么结果变了?

谢谢!

Let 不会复制任何东西,所以这会将变量 x 引用的值赋给变量 res。因此,对 res 引用的列表的任何更改也会更改 x

引用的列表

(let* ((res x) ; make a copy of X

为了清楚起见: 尽管您没有复制输入列表,但您的代码一点也不 lispy。试试这个:

(mapcar '1+ '(1 2 3 4))