user=> (eval '(+ 1 2))
3
user=> (eval '('+ 1 2))
2
user=> (eval (list '+ '1 '2))
3
user=> (eval (list + '1 '2))
3
這是否意味着「+有時從+一樣嗎?爲什麼在clojure(eval(list + 1 2))和(eval(list'+ 1 2))做同樣的事情?
有什麼規則來確定應考慮哪些情況?
user=> (eval '(+ 1 2))
3
user=> (eval '('+ 1 2))
2
user=> (eval (list '+ '1 '2))
3
user=> (eval (list + '1 '2))
3
這是否意味着「+有時從+一樣嗎?爲什麼在clojure(eval(list + 1 2))和(eval(list'+ 1 2))做同樣的事情?
有什麼規則來確定應考慮哪些情況?
(list '+ '1 '2)
產生符號列表+
和數字1
和2
。評估將查找由符號+
命名的函數和帶參數1
和2
調用它。
(list + '1 '2)
產生由符號+
命名的功能以及編號1
和2
的功能列表。評估它將調用已經直接作爲列表元素的函數,並使用來自列表其餘部分的參數。
從未有必要引用的數字,順便說一句。他們自我評估。
編輯:
更有趣的情況下,你沒有在你的標題地址是在(eval '('+ 1 2))
情況下會發生什麼?爲什麼會出現這種不返回3
像其他情況下,所有最終調用由+
的論據1
和2
命名的函數?
答案是,它是不同的,因爲這個時候,你所引述的符號+
的兩倍。因此,符號不會被解析爲它所命名的函數,而是符號本身被稱爲函數。
現在什麼是當一個符號被作爲函數調用的行爲?它將其第一個參數視爲地圖,並將其視爲該地圖中的關鍵字。但是號碼1
顯然不是地圖,所以現在通常會返回nil
來指示找不到匹配的密鑰。
在這種情況下,雖然,有第二個參數來調用符號+
,並且第二個參數被用作默認值時,沒有發現匹配鍵返回。所以這就是爲什麼表格(eval '('+ 1 2))
返回2
。
編輯2:
OK,現在終於回答這個問題:爲什麼引用列表產生不同的結果不是調用list
功能具有相同的參數。這是因爲報價'
停止它用在列表上的所有評價,但list
功能與他們產生一個列表作爲元素之前評估其論點。
這些差異在打印各種形式,而不是直接發送到eval
的一切都變得很清楚:
user> '(+ 1 2)
(+ 1 2)
user> '('+ 1 2)
((quote +) 1 2)
user> (list '+ '1 '2)
(+ 1 2)
user> (list + '1 '2)
(#<core$_PLUS_ [email protected]> 1 2)
你看,第一和第三種情況產生打印同樣的結果,因爲在這兩種這些案例你曾經引用過+
。在第二種情況下,+
是引用而不是兩次,並在最後它不是在所有的報價。
編輯3:
最後一個除了應該有希望進一步澄清的事情:除非它的第一個元素名稱的宏或特殊的運算符,eval
將遞歸評估列表中的所有元素(包括第一)前通過將其(被評估的)第一個參數作爲函數與列表的其餘部分作爲參數來評估列表本身。
如果第一個元素是'+
或(quote +)
(這些都寫一樣的東西,所引用的符號+
兩種不同的方式),將評估的符號+
,並且將被稱爲功能。
如果第一個元素是+
,那麼將評估爲實際加法函數(clojure.core$_PLUS_
)。如果它已經是該功能,它將保持不變(除了列表和符號之外,基本上所有類型都是自我評估的)。在這兩種情況下,eval
都會調用該函數。