2012-01-12 95 views
3

Clojure宏的noob在這裏。我有一個帶有一些可選參數的函數,例如如何將可選的宏參數傳遞給函數

(defn mk-foo [name & opt] 
    (vec (list* name opt))) 

給這個:

user> (mk-foo "bar" 1 2 3) 
["bar" 1 2 3] 

我想編寫一個宏,其採用相同的可選參數和透明地傳遞他們的mk-foo調用。到目前爲止,我有這樣的:

(defmacro deffoo [name & opt] 
    `(def ~name ~(apply mk-foo (str name) opt))) 

其中有預期的效果:

user> (macroexpand '(deffoo bar 1 2 3)) 
(def bar ["bar" 1 2 3]) 

採用apply拼合列表opt感覺笨拙。有沒有一種慣用的方式來做到這一點?我猜[email protected]是必要的,但我不能得到引用的權利。非常感謝。

+1

我不是特別擅長clojure,但它對我來說看起來很好! – 2012-01-12 22:02:03

回答

3

在這種情況下,你對使用apply的直覺很好。當你有一個引用的表格`,然後unqote所有這些可以幫助考慮將未引用的內容移動到最小的部分或列表中。這避免了使用代碼來生成可以簡單寫入的表單。

user=> (defmacro deffoo [name & opt] `(def ~name [~(str name) [email protected]]))  
#'user/deffoo 
user=> (macroexpand '(deffoo "bar" 1 2 3))        
(def "bar" ["bar" 1 2 3]) 

,並在這裏它與調用MK-FOO:

(defmacro deffoo [name & opt] `(def ~name (mk-foo ~(str name) [email protected])))  
#'user/deffoo 
user=> (macroexpand '(deffoo "bar" 1 2 3))         
(def "bar" (user/mk-foo "bar" 1 2 3)) 

在第二種情況下,我們移動在一個水平~,讓呼叫MK-FOO留報價,只是所享有建立參數列表所需的參數(使用拼接 - 無引號,如你所懷疑的)

+0

感謝您的快速回答。不幸的是,我的現實生活中的'mk-foo'比發佈的插圖要複雜得多。這不是手動內聯擴展它的選項。我必須接電話。 – fizzer 2012-01-12 22:52:36

+0

使用以前的編輯之一中的mk-foo重新啓動了該示例。 – 2012-01-13 02:35:53

+0

這個工作方式,+1,但延遲調用'mk-foo'來運行時間。 – fizzer 2012-01-13 12:39:30