lisp - push 没有像我预期的那样工作 - 为什么?

标签 lisp common-lisp

我遇到了一个我没有得到的 push 函数的行为。也许有人可以向我解释为什么 Lisp 会这样。

假设我将一个列表定义为全局变量,然后尝试使用以下代码向其推送一个新值:

(defparameter *primes* '(3 5 7 11))
(push 2 *primes*)

那么 *primes* 现在是 (2 3 5 7 11)。到目前为止,还不错。

现在我尝试做同样的事情,但没有 *primes* 变量,即:

(push 2 '(3 5 7 11))

结果是一条错误信息:

EVAL: 3 is not a function name; try using a symbol instead

现在我有两个问题:

  1. 为什么这不起作用?我希望 push 返回列表 (2 3 5 7 11),为什么这没有发生?我哪里错了?
  2. 除此之外,我没有收到错误消息。 Lisp 试图用 3 is not a function name 告诉我什么?当然,3 不是函数名,但我不会尝试在任何地方调用名为 3 的函数,对吗?

感谢任何帮助:-)

最佳答案

如果您阅读 PUSH 的 CL Hyperspec ,您会读到 push 需要一个位置

place 类似于变量、结构槽、类槽、数组访问或类似的东西。由于 Lisp 对列表使用链接的 cons 单元,因此在没有引用的情况下将某些东西推到 cons 单元前面是没有意义的。

所以上面很简单:我们不能推送到直接列表。

为什么会出现此错误消息?

这有点复杂...

(push 2 '(3 5 7 11))

实际上是:

(push 2 (quote (3 5 7 11))

一个函数可以是一个地方,那么它就需要一个对应的setter函数。这里的 setter 被认为是 (setf quote) - 没错,Common Lisp 有时可以将 list 作为函数名称,而不仅仅是符号。

如果我们看一下上面的宏展开:

? (pprint (macroexpand '(push 2 (quote (3 5 7 11)))))

(LET* ((#:G328 2) (#:G327 (3 5 7 11)) (#:G326 (CONS #:G328 '#:G327)))
  #:G327
  #:G326
  (FUNCALL #'(SETF QUOTE) #:G326 #:G327))

您可以看到它尝试调用 setter 。但它也认为 (3 5 7 11) 是 Lisp 形式。

我给你一个例子,它实际工作的地方,但我们不使用quote,而是一个真正的访问器函数:

CL-USER 40 > (let ((v (vector (list (list 'a 'b 'c) (list 'd 'e 'f))
                              (list (list 1 2 3)    (list 4 5 6)))))
               (print v)
               (push 42 (first (aref v 1)))
               (print v)
               (values))

#(((A B C) (D E F)) ((1 2 3) (4 5 6))) 
#(((A B C) (D E F)) ((42 1 2 3) (4 5 6))) 

在上面first 是getter,CL 知道相应的setter。形式 (aref v 1) 是调用并返回向量的索引 1 元素。然后我们将推送到元素的 first 列表。

您的调用具有相似的结构,(3 5 7 11)(aref v 1) 处于相似的位置。 Lisp 系统表示在 (3 4 7 11) 中,数字 3 不是有效函数。哪个是对的。但真正的错误是关于 push 操作。由于宏无法检测到错误,因此稍后会在宏扩展代码中检测到错误。

关于lisp - push 没有像我预期的那样工作 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23983629/

相关文章:

common-lisp - 我的宏如何采用变量而不是不带引号的列表?

dll - 从 lisp 脚本、工作目录和路径加载库

qt - Qt + Lisp 有什么好的实现吗?

lisp - Common Lisp : Destructure a list in first, rest,最后(像 Python 可迭代解包)

scheme - 从方案中的列表中打印对

lisp - 如何从列表中删除子列表?

lisp - 通过嵌套列表 LISP 递归

loops - 非法语法错误

function - Lisp 匿名函数局部变量

lisp - "Cons"在 Lisp 中如何工作?