2014-10-08 71 views
2

大概稱號,是不是100%正確,但讓我告訴你這個問題:另一個宏裏面的Clojure宏:如何從符號生成的字符串

(defmacro nvp! 
    [n width height] 
    `(q/defsketch (symbol (str (name '~n) "-viewport")) 
        :title (name '~n)) 

總之:有一個宏觀稱爲defsketch(它的一部分的lib quil,但這並不重要)。它的簽名基本上是defsketch [applet-name & options],它創建了一些東西並將其綁定到名爲applet-name的變量。出於某種原因,我想將其包含在另一個宏中,其中包含applet-name參數,將該名稱擴展爲applet-name-viewport,並將其傳遞給defsketch。我,但是,我無法弄清楚如何做正確(使用macroexpand在上面的代碼((pprint (macroexpand(nvp test-name 500 500))),我得到

(def(clojure.core/symbol (clojure.core/str (clojure.core/name 'my-namespace.core/test-name) "-viewport")) 
(quil.applet/applet 
:title (clojure.core/name 'my-namespace.core/test-name))) 

(clojure.core/symbol (clojure.core/str (clojure.core/name 'my-namespace.core/test-name) "-viewport") - 這部分看起來不錯,但它應該以某種方式傳遞之前,將進行評估到內部宏...

回答

3

您需要解除引用產生新的符號,而不是原始符號本身的形式。

這裏是如何做到這一點使用defn類似宏的一個小例子內部宏:

(defmacro mydefn 
    [name & body] 
    `(defn ~name [email protected])) 

(defmacro defnview 
    [n & body] 
    `(mydefn ~(symbol (str (name n) "-viewport")) [email protected])) 

;; OR 

(defmacro defnview 
    [n & body] 
    (let [n (symbol (str (name n) "-viewport"))] 
    `(mydefn ~n [email protected]))) 

例子:

(defnview foo [a] a) 
;; => #'user/foo-viewport 

(foo-viewport 1) 
;; => 1 

(macroexpand '(defnview foo [a] a)) 
;; => (def foo-viewport (clojure.core/fn ([a] a))) 
+0

感謝 - 這不是完全清楚尚未雖然。在你的例子中,你沒有調用第二個宏 - 我需要這樣做,第二個宏的參數應該是外部宏參數的變種版本。 – 2014-10-08 16:16:31

+0

@MateVarga它不會有所不同,因爲你正在返回一個新的表單 - 如果這恰好是一個宏,它將被擴展。我會用一個內部宏來更新我的答案。 – Kyle 2014-10-08 16:20:05

+0

非常感謝,我現在明白了。我對clj很感興趣,而且在2周之後宏已經有一段時間了:) – 2014-10-08 16:26:30