【问题标题】:Understanding variable scope in given code了解给定代码中的变量范围
【发布时间】:2020-02-11 15:16:28
【问题描述】:

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

这是我编写的代码(cmets 表示我在每个步骤中尝试做什么):

(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 本身。那么为什么结果会发生变化呢?

谢谢!

【问题讨论】:

    标签: scope lisp elisp


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      Let 不会复制任何内容,因此它将变量x 引用的值分配给变量res。因此,对res 引用的列表的任何更改也会更改x 引用的列表

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

      【讨论】:

      • 谢谢!好吧,我认为这是我在 Lisp 编程中真正不了解的(与我习惯的其他语言相比)。如果我理解得很好,当我用let(或setq)声明一个变量x并给它另一个变量y的值时,那么xy就变成了基本相同的对象,并且它们是“双向”链接的吗?对x 所做的任何更改都会动态影响y反之亦然
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      • 2017-04-08
      • 1970-01-01
      相关资源
      最近更新 更多