Reputation: 7213
Let's say I have come across a class with several static setter methods that I'd like to call in a row. The functionality I'm looking for is similar to that provided by doto, except that it must work on a class instead of an object:
(doto MyClass
(setA "a")
(setB "b"))
Unfortunately, when I try this, I get RuntimeException: Unable to resolve symbol: setA
. Is there a special doto
macro for classes?
Upvotes: 2
Views: 418
Reputation: 7213
I will leave this question open, since I'm hoping there's a better answer, but here's my home-grown macro to solve this problem:
(defmacro doto-class
"Calls a series of static methods on a class"
[klass & forms]
(cons 'do
(for [f forms]
`(. ~klass ~f))))
which expands the example:
(macroexpand-1
'(doto-class MyClass
(setA "a")
(setB "b")))
to
(do (. MyClass (setA "a"))
(. MyClass (setB "b")))
Upvotes: 2
Reputation: 13473
How do you call a static Java method from Clojure? Like this ...
(Classname/staticMethod args*)
For example,
> (System/getProperty "java.vm.version")
=> "25.141-b15"
We want a macro, say doto-static
, that re-arranges this from (doto-static System (getProperty "java.vm.version"))
, and also allows a chain of calls.
Such a macro is ...
(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))))
For example,
> (doto-static System (getProperty "java.vm.version") (getProperty "java.vm.version"))
=> "25.141-b15"
Upvotes: 1