从Clojure调用一系列Java静态方法

时间:2018-03-31 16:41:39

标签: clojure clojure-java-interop

假设我遇到了一个类,我想连续调用几个静态setter方法。我正在寻找的功能类似于doto提供的功能,除了它必须在类而不是对象上工作:

(doto MyClass
      (setA "a")
      (setB "b"))

不幸的是,当我尝试这个时,我得到RuntimeException: Unable to resolve symbol: setA。类是否有特殊的doto宏?

2 个答案:

答案 0 :(得分:2)

我会把这个问题保持开放,因为我希望有更好的答案,但这是我的本土宏来解决这个问题:

(defmacro doto-class
  "Calls a series of static methods on a class"
  [klass & forms]
  (cons 'do
        (for [f forms]
          `(. ~klass ~f))))

扩展了示例:

(macroexpand-1
 '(doto-class MyClass
              (setA "a")
              (setB "b")))

(do (. MyClass (setA "a"))
    (. MyClass (setB "b")))

答案 1 :(得分:1)

如何从Clojure调用静态Java方法?像这样......

(Classname / staticMethod args *)

例如,

> (System/getProperty "java.vm.version")

=> "25.141-b15"

我们想要一个宏,比如说doto-static,可以从(doto-static System (getProperty "java.vm.version"))重新安排这个,并且还允许一连串的调用。

这样的宏是......

(defmacro doto-static [class-symbol & calls]
  (let [qualify (fn [method-symbol] (->> method-symbol
                                    (name)
                                    (str (name class-symbol) \/)
                                  (symbol)))
        elaborate (fn [[method-symbol & arg-exprs]]
                      (cons (qualify method-symbol) arg-exprs))]
          (cons 'do (map elaborate calls))))

例如,

> (doto-static System (getProperty "java.vm.version") (getProperty "java.vm.version"))

=> "25.141-b15"