创建一个宏以返回一个reify(java接口),但在clojure中使用提供的带引号的表达式
我试图实现的是在宏中实现一个带有具体化的抽象类,但是应该在扩展时返回的表达式将提供给宏:创建一个宏以返回一个reify(java接口),但在clojure中使用提供的带引号的表达式,clojure,Clojure,我试图实现的是在宏中实现一个带有具体化的抽象类,但是应该在扩展时返回的表达式将提供给宏: (defmacro a-printable [body] `(reify Printable (print [this g# pf# page#] (if (= page# 0) (do ~body ;; the supplied part (Printable/PAGE_EXISTS)) (Printable/NO_SUCH_PAGE))) (def exp '(do
(defmacro a-printable
[body]
`(reify Printable
(print [this g# pf# page#]
(if (= page# 0)
(do
~body ;; the supplied part
(Printable/PAGE_EXISTS))
(Printable/NO_SUCH_PAGE)))
(def exp '(do (.translate g (.getImageableX pf) (.getImageableY pf))
(.drawString g "foo" 10 10))) ;; the form to pass
(a-printable exp)
问题是,在我传递的表达式中,我想使用在宏和具体化g#,pf#
中定义的自动生成的变量。
我尝试添加带有(ns resolve*ns*g)
(ns resolve*ns*pf)
的引用表达式,但我不确定宏中是否正在解析该表达式。
g
是java.awt.Graphics
这是一个抽象类,pf
是java.awt.print.PageFormat
,这是一个带构造函数的普通类。
有人知道如何做到这一点,或者把我引向正确的方向吗?我相信诀窍在于,如果你不想在宏中使用带名称空间的符号,你可以在它们前面加上
~'
,例如~'g
。然后,我对宏进行了以下其他修改:
主体
参数前面加上&
前缀,使其长度可变(可打印/PAGE\u存在)
和(可打印/NO\u页面)
周围的括号:这些是要返回的静态变量值,而不是函数调用李>
这就是固定宏的外观:
(defmacro a-printable
[& body]
`(reify Printable
(print [~'this ~'g ~'pf ~'page]
(if (= ~'page 0)
(do
~@body ;; Splice it!
Printable/PAGE_EXISTS)
Printable/NO_SUCH_PAGE))))
这就是创建实例的方法。请注意,我不需要使用do
将参数包装到宏中:
(def p (a-printable
(.translate g (.getImageableX pf) (.getImageableY pf))
(.drawString g "foo" 10 10)))
但是需要注意的是:我不确定引入新符号(如pf
和g
)是否是一种好的做法,但我找不到提及为什么这种做法不好的参考文献。有一些方法可以实现与本问题中所问内容类似的功能,而无需借助宏。不使用宏的版本不会太长:
(defn a-printable-fn [body-fn]
(reify Printable
(print [this g pf page]
(if (= ~'page 0)
(do
(body-fn this g pf page)
Printable/PAGE_EXISTS)
Printable/NO_SUCH_PAGE))))
(def p (a-printable-fn
(fn [this g pf page]
(.translate g (.getImageableX pf) (.getImageableY pf))
(.drawString g "foo" 10 10))))
首先感谢您抽出时间回答我的问题。其次,我想问,为什么我更喜欢函数版本,我想,因为我想传递引用表达式宏是我应该做的事情。这将是一个坏的做法,一般来说,使用宏时,我可以做同样的功能?