Nicolas Modrzyk
Nicolas Modrzyk

Reputation: 14197

Clojure, Java Interop and proxy-ed methods

So, let's say I have this abstract class in Java named MyFunction, that has an abstract evaluate method.

To use this in clojure, I can do:

(def java-function
 (proxy [MyJavaFunction] []
   (evaluate [x]
     (* x 2))))

And then call it with:

 (.evaluate java-function 3)

returning

 ; => 6

What would be a nice way of turning the above into something more clojure:

  (java-function 3)

that would also be returning

 ; => 6

Upvotes: 2

Views: 159

Answers (1)

Michał Marczyk
Michał Marczyk

Reputation: 84341

You can accomplish that by implementing the clojure.lang.IFn interface:

((proxy [clojure.lang.IFn] []
  (invoke [x]
    (str "A very a nice x indeed: " x)))
 3)
;= "A very a nice x indeed: 3"

To have your proxy subclass MyFunction and implement IFn, mention them both in the first argument to proxy; NB. the class goes first:

(proxy [MyFunction clojure.lang.IFn] []
  ...)

Actually the above implementation is incomplete – you'll also want to implement the applyTo method that takes a single seq argument apart from this and is used by apply. There are also separate invoke methods for other fixed arities (up to 20). Follow this link to data.avl's sources (release 0.0.12) to see an applyTo implementation delegating to the appropriate invoke method while taking care to avoid going into an infinite loop / taking an inordinate amount of time if the seq that was passed in happens to be infinite / very long.

Upvotes: 5

Related Questions