如何在defmacro中保留元标记

时间:2018-10-05 08:55:37

标签: clojure

如何定义宏以保留元数据信息?

(defmacro defdynamic
  [name val]
  (let [dname (symbol (str "*" name "*"))]
    `(def ^:dynamic ~dname ~val)))

(defdynamic hello 1)

会给出警告:

Warning: *hello* not declared dynamic and thus is not dynamically
rebindable, but its name suggests otherwise. Please either indicate
^:dynamic *hello* or change the name.

并且var不会是动态的

(:dynamic (meta #'*hello*))
=> nil

1 个答案:

答案 0 :(得分:2)

您将meta放在错误的位置。

(defmacro defdynamic
    [name val]
    (let [dname (-> (str "*" name "*")
                    (symbol)
                    (with-meta {:dynamic true}))]
        `(def ~dname ~val)))

^:dynamic ~dname不起作用,因为它等效于 (with-meta (unquote dname) {:dynamic true})。因此,meta用于取消引用本身,而不是最终结果。