为什么 (find-if #'consp '('notdefinedsymbol)) => 'NOTDEFINEDSYMBOL?

Why does (find-if #'consp '('notdefinedsymbol)) => 'NOTDEFINEDSYMBOL?

此代码来自 emacs 缓冲区 slime-repl sbcl :

CL-USER> (consp 'notdefinedsymbol)

NIL

CL-USER> (find-if #'consp '('notdefinedsymbol))

'NOTDEFINEDSYMBOL

如果 consp returns nil 那么为什么 find-if 就像 consp returns 一个真值一样?

With (consp 'notdefinedsymbol) consp in operator position is a symbol for the #'consp function and thus it's argument (quote notdefinedsymbol), abstracted as just 'notdefinedsymbol needs to申请前进行评估。 A (quote x) 对数据 x 求值,因此在我们的例子中,参数变为符号 notdefinedsymbol。它不是 cons 而是 symbolp 因此结果是 nil

第二个你有 (find-if #'consp '('notdefinedsymbol)),因为 find-if 是一个函数,它会计算它的参数。 #'consp 计算函数对象,'('notdefinedsymbol)(quote ((quote notdefinedsymbol))) 的缩写。与往常一样,它评估其参数 ((quote notdefinedsymbol))。它是一个包含一个元素的列表,它本身是一个包含两个元素的列表,符号 quotenotdefinedsymbol。由于 (consp '(quote notdefinedsymbol) ; ==> t find-if 的计算结果为 (quote notdefinedsymbol) 并且一些 CL 打印机将缩写两个元素的列表,其中第一个元素是 quote,其方式与 reader 相同宏和打印 'notdefinedsymbol 但它仍然是两个元素的列表,因为它不是代码,而是数据。

你的错误当然是你嵌套了引号。如果你这样做了,你会得到你预期的结果:

(find-if #'consp '(notdefinedsymbol)) ; ==> nil

(consp 'a) - 首先计算函数参数。所以我们有:'a 计算结果为:a。那是一个原子,因此 NIL.

(find-if #'consp '('a)) 也首先评估参数。但是对于列表的第一个参数,它测试 'a 是否是一个缺点。是的,因为那是 (quote a) (只评估列表的外部 ',而不评估 a 前面的内部,因此 'a.

a = notdefinedsymbol.

您的调用:(find-if #'consp '('not-defined-symbol)) 与(即由 reader 扩展为)(find-if (function consp) (quote ((quote not-defined-symbol)))) 相同。参数 (quote ((quote not-defined-symbol))) 被评估为列表 ((quote not-defined-symbol))(即包含包含两个符号 quotenot-defined-symbol 的列表的列表)。 Find-if 遍历外部列表,测试内部列表,这是一个缺点,consp 表示 true,returns 它。

你想做的最有可能是:(find-if #'consp '(not-defined-symbol))等同于 (find-if (function consp) (quote (not-defined-symbol))。注意:没有嵌套引号。

查看 the docs for quote and the CLHS chapter about evaluation 以获得更好的理解。