为什么这个引用形式没有按预期进行评估

时间:2013-11-01 07:03:05

标签: lisp common-lisp

我有一个简单的功能:

(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形式吗?

2 个答案:

答案 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)))