为什么 (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))
。它是一个包含一个元素的列表,它本身是一个包含两个元素的列表,符号 quote
和 notdefinedsymbol
。由于 (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))
(即包含包含两个符号 quote
和 not-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 以获得更好的理解。
此代码来自 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))
。它是一个包含一个元素的列表,它本身是一个包含两个元素的列表,符号 quote
和 notdefinedsymbol
。由于 (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))
(即包含包含两个符号 quote
和 not-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 以获得更好的理解。