I am writing Clojure code interacting with external Java library. One of the method returns Java Optional object. Let's assume that it returns Optional<String> and I need to change the string value in the Optional object, for example, to lowercase. I'd use map method if I write the code in Java:
Optional<String> ret = someObj.someMethod();
ret.map(String::toLowerCase)
.map(...)
.orElse("x");
So, I need to call someObj.someMethod() in Clojure and have to do the similar work. What I found is this: Passing a Clojure function as java.util.Function
So I wrote code like this:
(defn ^java.util.function.Function jfn [f]
(reify java.util.function.Function
(apply [this arg] (f arg))))
(let [ret (.someMethod someObj)]
(.. ret
(map (jfn (fn [x] (s/lower-case x))))
(map (jfn (...)))
(orElse "x")))
In order to pass clojure function to the place that expects Java lambda, I used jfn defined like the above. And actually it works fine.
But I am not sure this is the best way to do this as I have to wrap clojure function that calls Java method inside with Java's Function.
Are there any better/simpler way to do this? It will be better if we can call Java String's toLowerCase method directly.
Optionalearly on, and usesome->macro to do a similar operation. Even if you needed anOptionalwith the value later, it might be easier to re-box the value later than to do Function interop.jfna macro instead of a function:(defmacro jfn [[arg] & body] (reify Function (apply [_# ~arg] ~@body))), and then(.map ret (jfn [x] (s/lower-case x))).