2017-01-09 25 views
0

我正在探索基本示例的宏,我不明白它是如何工作的。Clojure:爲什麼這個宏不起作用?

此:

(defmacro evalf [f v] 
    (f v)) 
(evalf + 2) 

不起作用。

我想:

(defmacro evalf [f v] 
    '(f v)) 
(evalf + 2) 

沒有運氣...

我不明白其他語法:~~ @等等,但他們也不管用。我看到符號f沒有指向+,但我不知道要說「取f是+的值」。

你能說清楚嗎? 預先感謝

回答

4

取決於你想做的事做有兩個變種:

第一個(你可能想要的)是:

(defmacro evalf [f v] `(~f ~v)) 

(defmacro evalf [f v] (list f v)) 

它們都做同樣的事情:生成你需要的s表達式。 編譯時將(evalf + 10)擴展爲(+ 10),然後在運行時成功進行評估。

第二個是這樣的:

(defmacro evalf [f v] ((resolve f) v)) 

現在的功能f稱爲在編譯時間,所以宏將擴大到結果:10

您與(f v)變種默默地失敗,因爲當你撥打(evalf + 10), +這裏只是一個普通符號,而不是從宏觀角度來看函數的引用,所以它試圖調用('+ 10),因爲clojure中的符號具有函數的語義,所以它是完全正確的語法,但是這個調用產生了nil。 (符號調用的例子:('+ {'+ 10}) => 10)所以如果你想得到這個命名爲這個符號的函數,你將不得不解決它,就像我的第二個例子。

而且隨着'(f v)變異只是擴展到兩個符號列表:'f'v,然後導致運行時調用('f 'v)也返回nil,就像第一種變體。

+0

謝謝,都是答案,但我更瞭解你的,所以我選擇了這個 –

4

嘗試

(defmacro evalf [f v] 
    (list f v)) 

(evalf (partial * 2) 66); 132 

evalf

  • 的參數傳遞未計算的作爲形式(partial * 2)66所述呼叫;
  • 宏的主體產生表達式(list '(partial * 2) '66);
    • 其計算結果爲形式((partial * 2) 66)
    • 其中,從宏觀返回,計算結果爲132

一種替代,使用語法報價,是

(defmacro evalf [f v] 
    `(~f ~v))