Clojure - 如何在系统宏之前扩展我的宏?

时间:2011-02-13 13:53:59

标签: macros clojure

如果我这样做,例如:

(defmacro qqq [] '(toString [this] "Qqq"))
(reify Object (qqq))

由于reify看到(qqq)而不是(toString [this] "Qqq")而失败。

usual solution是一个用我自己的东西包裹“reify”调用的宏,但它更长,更具侵入性。

如何使我的宏更强大,以便首先扩展通常的宏?

期待类似的事情:

(defmacro ^{:priority 100500} qqq [] '(toString [this] "Qqq"))
(reify Object (qqq))

(defmacro qqq [] '(toString [this] "Qqq"))
(expand-first #{qqq} (reify Object (qqq)))

3 个答案:

答案 0 :(得分:7)

在读取时(宏扩展时间之前)有一个读取器宏来评估事物。

(defn qqq [] '(toString [this] "Qqq"))
(reify Object #=(qqq))

我从来没有在"真实"代码,我想大多数人会认为这是一个黑客,但如果你需要它就会在那里。

答案 1 :(得分:1)

强制给定用户宏首先展开的宏(需要clojure.walk):

(defmacro expand-first [the-set & code] 
 `(do ~@(prewalk 
  #(if (and (list? %) (contains? the-set (first %)))
  (macroexpand-all %)
  %) code)))

谁有想法如何让它变得更好?

答案 2 :(得分:0)

这将有效:

(defn reifyx [x y]
  (eval `(reify ~x ~y)))

(defn qqq [] '(toString [this] "Qqq"))

(reifyx 'Object (qqq))

我找到了apply-macro。我试了一下,但好像坏了。我在查看apply-macro时收集的最重要的事情是它使用eval解决了问题,就像我一样。