我有一个简单的功能:
(defun ifelse (the-test)
(cond (the-test (format t "passed test, true!"))
(t (format t "failed test, boo hoo"))))
如果我这样做,我会得到你所期望的:
(ifelse (funcall (lambda () nil)))
failed test, boo hoo
NIL
我很好奇为什么这不会导致“失败”:
CL-USER> (ifelse '(funcall (lambda () nil)))
passed test, true!
NIL
我的想法是,不是评估funcall
到位,然后将返回值传递给ifelse
,而是将整个funcall
无评估地传递到ifelse
- 但是,如何在函数内处理引用的形式?难道它不会被原地复制,然后被视为真正的Lisp形式吗?
答案 0 :(得分:4)
让我们看看你到底得到了什么:
(defun return-argument (element) element)
[9]> (defun return-argument (element) element)
RETURN-ARGUMENT
[10]> (return-argument (funcall (lambda () nil)))
NIL
好的,这是预期的。现在你的第二个函数调用,导致失败。
[11]> (return-argument '(funcall (lambda () nil)))
(FUNCALL (LAMBDA NIL NIL))
啊,这给了我们一个线索。我们不评估论证,因为它引用了。事实上,我们可以看到我们将其作为列表重新获取:
[19]> (listp (return-argument '(funcall (lambda () nil))))
T
请记住,当你引用某些内容时,就会阻止它被评估。
注意:return-argument
与内置identity
功能相同。我写了一个新的,所以你可以看到它在幕后做了什么。
答案 1 :(得分:0)
在示例中,您将列表作为参数传递(因为引用)。 您需要使用eval来评估引用的列表以使其“失败”。 像这样
(ifelse (eval '(funcall (lambda () nil))))
或删除引用
(ifelse (funcall (lambda () nil)))