clojure - 创建一个宏以返回一个 reify(java 接口),但在 clojure 中提供了带引号的表达式
问题描述
我想要实现的是在宏内部实现一个带有 reify 的抽象类,但是应该在扩展时间返回的表达式将提供给引用的宏:
(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)
问题是在我传递的表达式中,我想使用在宏和 reify 内部定义的自动生成的变量g#, pf#
。我尝试添加带引号的表达式, (ns-resolve *ns* g)
(ns-resolve *ns* pf)
但不缺少,我不确定在宏内部是否已解决。g
isjava.awt.Graphics
是一个抽象类,ispf
是java.awt.print.PageFormat
带有构造函数的普通类。有谁知道如何实现这一目标,或者让我转向正确的方向?
解决方案
我相信诀窍是,如果您不想在宏中使用命名空间符号,您可以在它们前面加上~'
, 例如~'g
. 然后我对您的宏进行了以下其他修改:
body
为参数加上前缀&
以使其可变长度。- 将body拼接成宏
(Printable/PAGE_EXISTS)
删除and周围的括号(Printable/NO_SUCH_PAGE)
:这些是您要返回的静态变量值,而不是函数调用。
这是固定宏的样子:
(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
and 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))))
推荐阅读
- json - python中有没有办法将值添加到键中而不是替换json文件中的现有值?
- excel - Excel 用冒号格式化字符串
- elasticsearch - 在 Elasticsearch 中,如何按嵌套字段的属性对检索到的结果进行排序
- c++ - C++ 求职面试问题变得更难了,如何解决?
- java - 在 Java 中,ArrayList 始终读取为 .size() 0 到 while 循环,即使它是在创建时实现的
- java - 关于客户端锁定(同步块)的 CoreJava 第 11 版线程问题
- ruby-on-rails - 此代码中引用的模型关联行的 3.1 版本在哪里
- jquery - 滚动停止时,浮动 div “捕捉”到最近的 tr
- javascript - 如果使用具有相同值的分组列表,如何获得唯一的活动元素
- node.js - 提高 Redis Lua 脚本性能