此代码来自emacs缓冲区slime-repl sbcl:
CL-USER>(consp'notdefinedsymbol)
NIL
CL-USER>(查找是否为#'consp'('notdefinedsymbol))
'NOTDEFINEDSYMBOL
如果consp返回nil,那么为什么find-if表现为consp返回真值?
将(consp 'notdefinedsymbol)
置于consp
位置是#'consp
函数的符号,因此它是参数(quote notdefinedsymbol)
,简称为'notdefinedsymbol
,需要在应用之前进行求值。 (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
,其方式与阅读器宏相同,并打印'notdefinedsymbol
,但它仍然是列表因为它不是代码,而是数据,所以它是两个元素。
您的错误当然是嵌套引号。如果您这样做,您将获得预期的结果:
(find-if #'consp '(notdefinedsymbol)) ; ==> nil
(consp 'a)
-首先对函数参数求值。因此,我们得到:'a
评估为:a
。那是一个原子,因此NIL
。
(find-if #'consp '('a))
也首先取消参数。但是对于列表的第一个参数,它将测试'a
是否不利。因为是(quote a)
(仅评估列表的外部'
,因此不评估a
前面的内部,因此,'a
。)
a = notdefinedsymbol
。