2013-11-01 46 views
0

我有一個簡單的函數,工作原理:爲什麼沒有這個引號形式評估預期

(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 

我的想法是,而不是在PL評估funcall ace,然後將返回值傳遞到ifelse,整個funcall被傳遞到ifelse未被評估 - 但是,函數中如何處理引用的表單?難道它本質上不會被複制,然後被視爲真正的Lisp形式嗎?

回答

0

在該示例中,您傳遞一個列表作爲參數(因爲引用)。 您需要使用eval來評估所引用的列表以具有「失敗」。 這樣

(ifelse (eval '(funcall (lambda() nil)))) 

或刪除該帖

(ifelse (funcall (lambda() nil))) 
+0

我建議不要在這裏使用'eval'。首先,你不需要它:爲什麼你想要通過一個列表,並期望它被評估?這很愚蠢。內置的'if'不能這樣工作。你打開自己的東西,如不能訪問代碼中其他地方定義的變量。引用列表不是虛假的原因不是「因爲你需要評估」;原因是「因爲你通過了一個列表,列表是真的」。 – zck

4

讓我們來看看你實際得到:

(defun return-argument (element) element) 

[9]> (defun return-argument (element) element) 
RETURN-ARGUMENT 
[10]> (return-argument (funcall (lambda() nil))) 
NIL 

OK,這是符合市場預期。現在你的第二個函數調用,導致失敗。

[11]> (return-argument '(funcall (lambda() nil))) 
(FUNCALL (LAMBDA NIL NIL)) 

啊哈,這給了我們一個線索。我們不評估論據,因爲它被引用。事實上,我們可以看到我們正在回來的列表:

[19]> (listp (return-argument '(funcall (lambda() nil)))) 
T 

記住,當你引用的東西,你防止它被評估。

注:return-argument與內置的identity功能相同。我寫了一個新的,所以你可以看到它在做什麼。

+0

非常有用,謝謝 – johnbakers

相關問題