第一个不起作用。 但第二个工作,这让我感到困惑.. 有人可以解释一下吗?
CL-USER> (funcall (first '(#'+ +)) 1)
; Evaluation aborted on #<TYPE-ERROR expected-type:
; (OR FUNCTION SYMBOL) datum: #'+>.
CL-USER> (funcall #'+ 1)
1
答案 0 :(得分:4)
#'
是读者宏。 #'+
是(function +)
的缩写。 '
是一个扩展到(quote …)
的读者宏。后者返回其论点未评估。因此,'(#'+ +)
会产生((function +) +)
(#'+
将在读取时变为(function +)
。 first
只是列表(function +)
,它不是函数。现在,(function +)
打印为#'+
,这是您在调试器中看到的内容。
使用非文字列表将起作用:
CL-USER> (funcall (first (list #'+ '+)) 1)
1
答案 1 :(得分:4)
您的输入是:
(funcall (first '(#'+ +)) 1)
我们评估时'(#'+ +)
是什么?前面的引用阻止了表单的评估,因此结果就是读者读取的数据:
这是一个包含两个项目的列表:
(function +)
+
通常写为((function +)+)。
请注意,原始输入中的引号明确表示您不想评估列表或其内容。
现在,您可以在此列表中拨打FIRST
。结果是第一项:(function +)
。这是两个项目的列表:
function
+
现在使用此列表调用FUNCALL,值为1。
FUNCALL期望函数或符号作为输入。您将列表(function +)
作为第一个参数。 FUNCALL不知道如何处理它。
我们如何修复它?您可能想要使用评估(function +)
的结果的函数。
因此您需要重写原始列表。而不是''(#'+ +))'使用例如:
(list #'+ '+)
或
`(,#'+ +) ; note the backquote in front