【问题标题】:a macro that creates object in clojure在 clojure 中创建对象的宏
【发布时间】:2019-02-26 16:27:13
【问题描述】:

我正在尝试创建一个宏,在 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 修复了对象创建问题。

【问题讨论】:

    标签: clojure macros


    【解决方案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 您试图将其视为一个序列,这是行不通的,因此会出现错误。

    【讨论】:

    • 谢谢,它有效!如果我将 java.lang.Object 提取为函数或 def 我得到空指针异常:/ (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)))
    • 当您评估 (create-obj-with-proxy foo) 时,符号 foo 必须评估为一个类。 give-me-class 不是一个类的符号,这就是为什么上面的方法不起作用。所以你会得到类似 java.lang.ClassCastException: clojure.lang.Var cannot be cast to java.lang.Class 的错误。
    • 有没有办法让结果成为一个类?我试过(给我上课)
    • 宏不会像函数那样首先评估它们的参数。看看你要写的东西的宏扩展,然后我希望它应该很清楚。
    • 我试过(defmacro create-obj-with-proxy [klass] (proxy [~(class klass)] [] (toString [] (str "proxyToString"))))`和(defmacro create-obj-with-proxy [klass] (proxy [~(class ~klass)] [] (toString [] (str "proxyToString"))))` 都导致CompilerException java.lang.ClassCastException: java.lang.Class cannot be cast to clojure.lang.Symbol,
    猜你喜欢
    • 1970-01-01
    • 2013-12-01
    • 2015-07-29
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 2014-02-15
    相关资源
    最近更新 更多