在Clojure中创建对象的宏

时间:2018-09-22 14:33:28

标签: clojure macros

我正在尝试创建一个宏,该宏使用注释在Clojure中动态创建Java对象。

我一直在尝试proxyreify,但都没有成功面对CompilerException

到此为止:

代理

第一个尝试是创建一个没有宏的对象:

(.toString 
  (proxy [java.lang.Object] [] 
    (toString [] (str "proxyToString"))))

其结果为:=> "proxyToString"

然后我尝试用一​​个宏将其包装并传递object作为参数:

(defmacro create-obj-with-proxy [klass]
  `(proxy [~klass] [] (toString [] (str "proxyToString"))))

其结果为:=> #'oppose/create-obj-with-proxy

我可以对其进行扩展或评估

(macroexpand (create-obj-with-proxy java.lang.Object))
(.toString (create-obj-with-proxy java.lang.Object))

它也可以与reify一起使用。

(defmacro create-obj-with-reify [klass]
  `(reify ~klass
              (toString [this] "reifyToString")))

(macroexpand (create-obj-with-reify java.lang.Object)) 
(.toString (create-obj-with-proxy java.lang.Object)

但是,如果我将类名与变量关联,则会得到异常

(def give-me-class java.lang.Object)
(def give-me-class-fn [] java.lang.Object)
(.toString (create-obj-with-proxy give-me-class))
(.toString (create-obj-with-proxy (give-me-class-fn)))


(.toString (create-obj-with-proxy give-me-class))
CompilerException java.lang.ClassCastException: clojure.lang.Var cannot be cast to java.lang.Class, compiling:

(.toString (create-obj-with-proxy (give-me-class-fn)))
CompilerException java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol, compiling:

有什么建议吗?

编辑:感谢@Michiel Borkent修复了对象创建问题。

1 个答案:

答案 0 :(得分:1)

您快到了,但是需要删除拼接运算符:

(defmacro create-obj-with-proxy [klass]
  `(proxy [~klass] [] (toString [] (str "proxyToString"))))

然后

(create-obj-with-proxy java.lang.Object)

将返回

#object[dre.compress.proxy$java.lang.Object$ff19274a 0x6c221bc8 "proxyToString"]

您正在传递符号自变量。使用unquote-splice,您尝试将其视为一个序列,该序列将不起作用,因此会出现错误。