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