2016-07-06 65 views
0

甲函數來添加一個和一個:爲什麼函數的返回值沒有被評估,但宏的返回值是?

(defn one-plus-one [] (list + 1 1))

時調用返回:

(#object[clojure.core$_PLUS_ 0x47fa7bd5 "[email protected]"] 1 1)

相同的功能體包裹在一個宏:

(defmacro one-plus-one [] (list + 1 1))

當被叫回報:

2

爲什麼Clojure的期望宏返回一個可評估的表情?

編輯

答案the possible duplicate question告訴宏是如何從一個功能有所不同。但是沒有回答原因。隱喻地說,我知道一個從高空遺留下來的物體會垂直下落到地面。我的問題是爲什麼它垂直下降?

+4

[defn和defmacro有什麼不同?](http://stackoverflow.com/questions/3667403/what-is-the-difference-between-the-defn-and-defmacro) –

+4

你應該閱讀更多關於宏我猜。您可以將宏調用看作是在編譯時用宏內容替換自己的代碼。因此,對於宏一加一的情況,你可以想象'(一加一)'將'(+ 1 1)'放入你的源代碼中,然後和其餘的源代碼一起評估。 – leetwinski

+1

重新編輯,並從[鏈接的問題](http://stackoverflow.com/a/3672068/425313)引用函數轉換值,宏將代碼轉換爲其他代碼。 –

回答

1

就讓我們先從一件事解釋宏,從而導致學習別人想想宏時是迷茫的時候很多人都知道這麼好,他們忘了明確想一想:

------ ----->宏是函數< -------------

它們通常用於獲取看起來像代碼的東西的列表,並且經常期望返回列表可以實際上作爲代碼運行。

宏和函數之間的區別並不在於它(從根本上),而在於它的作用。 宏在代碼「加載」時運行並且它們返回的值在程序運行時運行。

當你寫它作爲一個宏它兩個步驟:

  • 運行函數產生一個列表
  • 運行一個返回列表,代碼生成一個值

當你把它寫成一個功能它一步到位:

  • 運行函數產生一個列表

然後停止。

返回值是不同的,因爲宏版本需要額外的步驟來運行返回的值作爲代碼。

代碼是數據...數據是代碼... yay lisp!

+0

我一直在應用類似的思維過程來理解宏。在REPL過程中,宏位於Read和Eval之間。這就是爲什麼評估宏的返回值是因爲「讀取」已經發生。另一方面,函數被評估,並且它的返回值意味着被饋送給讀者。我可能是錯的。我還在想。 – ardsrk

+0

更多的想法是,函數的返回值打算打印出來,或者執行過程循環返回,並將返回值輸入到「讀取」步驟。 – ardsrk

+0

@ardsrk是的,你明白了。它會循環回讀階段,如果它仍然是第二階段的宏,那麼它會再次循環返回第三階段。只是繼續前進,直到沒有宏。那麼最終完全形成的代碼實際上會使它成爲完成的程序。 –