2

可能标题不是 100% 正确,但让我向您展示这个问题:

(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. 但是,我无法弄清楚如何正确地做到这一点(在上面的代码中使用宏扩展((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")-- 这部分看起来不错,但是在将它传递给内部宏之前应该以某种方式对其进行评估......

4

1 回答 1

3

您需要取消引用生成新符号的表单而不是原始符号本身。

这是一个小示例,说明如何使用defn内部宏的 like 宏来完成此操作:

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

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

;; OR

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

例子:

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

(foo-viewport 1)
;; => 1

(macroexpand '(defnview foo [a] a))
;; => (def foo-viewport (clojure.core/fn ([a] a)))
于 2014-10-08T16:03:35.890 回答