listp 的意外结果

unexpected result from listp

我有一个结构蜘蛛:

(defstruct spider omegas values k)

还有一个实例spider:

(set '*spider* (make-spider
  :omegas '()
  :values (list *input*)
  :k '(#'omegashift #'dec #'dupval '((0 . #'dec) (1 . #'inc) (2 . #'dec)))))

但是当我 运行 表达式:(listp (car (spider-k *spider*)) 在 Emacs 和 SBCL 上(涉及 SLIME 但我不确定它是什么。) REPL returns T。这显然令人困惑,因为 (car (spider-k *spider*) 正确 returns #'OMEGASHIFT(listp (function OMEGASHIFT)) 正确 returns NIL.

为什么 (listp (car (spider-k *spider*)) 是真的?不应该是假的吗?

#'omegashift 是一个扩展到列表 (function omegashift).

的 reader-宏

当您评估 (function omegashift) 时,您得到一个函数,但您没有评估它,因为您引用了列表。所以你只是得到 reader-宏扩展到的列表。

如果你这样做,你会看到同样的东西 (listp (car '('foo)))'foo 扩展到列表 (quote foo)。计算结果为符号 foo,但列表前的引号阻止计算。

要获取函数而不是列表,您需要计算函数表达式。您可以通过调用函数 list 而不是引用列表来做到这一点。

(setq *spider* (make-spider
  :omegas '()
  :values (list *input*)
  :k (list #'omegashift #'dec #'dupval (list (cons 0  #'dec) (cons 1  #'inc) (cons 2  #'dec)))))

你也可以使用反引号来简化这个:

(setq *spider* (make-spider
  :omegas '()
  :values (list *input*)
  :k `(,#'omegashift ,#'dec ,#'dupval '((0 . ,#'dec) (1 . ,#'inc) (2 . ,#'dec)))))

在反引号表达式中,您可以使用逗号来标记要计算的子表达式。

顺便说一句,你应该使用 setq 来分配变量,而不是带引号的 set 。它们等同于全局变量,但不能将 set 与局部变量一起使用。