gpt4 book ai didi

lisp - 无法更改列表

转载 作者:太空宇宙 更新时间:2023-11-03 18:50:52 25 4
gpt4 key购买 nike

例如,我有函数 stack-push 将元素压入堆栈。

(defun stack-push (stack element)
(if (not (listp element))
(setf stack (cons element stack))
(dolist (current-el (reverse element))
(setf stack (cons current-el stack)))))

但是当我像 (stack-push *some-stack* '(a b c d e)) 那样调用它时,它不会影响 *some-stack*。你能解释一下为什么吗?

最佳答案

setf 带有一个符号作为 (setf stack (cons element stack)) 扩展为 (setq stack (cons element stack))。这通常发生在您创建函数时。你的功能变成这样:

(defun stack-push (stack element)
(if (not (listp element)
(setq stack (cons element stack))
(dolist (current-el (reverse element))
(setq stack (cons current-el stack)))))

请注意,我在这里只扩展了 setfdefundolist 都变成了非常可怕的扩展,使代码更难读。系统完全展开表单,因此运行的代码没有宏。

setq 更新一个绑定(bind),所以当它更新 stack 时,它更新的就是它更新的内容,而不是 *some-stack*。如果您执行 (stack-push *some-stack* "a"),这正是发生的情况:

  1. 您传递函数 *some-stack*"a"。它评估其论点。
  2. *some-stack* 计算地址 A,它有一个 cons 单元格,例如。 ("b")
  3. "a" 是一个驻留在地址 B 的文字
  4. 参数被绑定(bind)到新的绑定(bind)。 stack指向A,element指向B。
  5. 因为 element 指向 B (not (listp element)) ; ==> t 代码在结果之后。
  6. in (setf stack (cons element stack)) 是在运行时更改为(setq stack (cons element stack))之前。
  7. (cons element stack) 以 B 和 A 作为参数调用 cons。返回地址为 C 的新单元格 ("a""b")
  8. setq 更新以便绑定(bind) stack 指向 C。
  9. stack-push 返回最后计算的值,这是 setq 的结果,即第二个参数 C。

函数中没有提到*some-stack*。绑定(bind)永远不会被引用或更新。只有 stack 更新了要指向的新值。

由于这是一个函数,您可以使用文字调用您的函数,如果参数是要更新的变量,这通常不会起作用。

(stack-push '("b") "a") ; ==> ("a" "b")

有一种形式叫做push。它不是函数。你可以看到它做了什么:

(macroexpand '(push "a" *some-stack*)) 
; ==> (setq *some-stack* (cons "a" *some-stack*))

因此,要使 push 正常工作,您需要第二个参数是 setf 可用的。用文字尝试它会扩展为无法运行的代码。对于类型,您可以制作自己的 setf 扩展器,这样 setfpush 就可以工作。

关于lisp - 无法更改列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50201198/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com