2014-10-08 61 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