8

I need to somehow tag certain Clojure functions as "special" so that Java code could recognize them as such using reflection. I've tried to add an annotation to a function, but apparently that's not supported. I've tried to reify an interface extending IFn (so that the Java code could recognize the function object), but that's no good because Clojure doesn't directly use the reified method as the code implementing invoke, but rather an indirect call to an Afunction object that's actually implementing the method (I need to tag the actual invoke method with the actual function code).

Any ideas?

EDIT: even tagging in a way that could be accessed with the ASM library (rather than regular reflection) would be fine, but I need to somehow tag the actual AFunction object or the invoke method. Also, I can't access the actual AFunction object -- I need the tag to be visible on the class.

pron
  • 1,693
  • 18
  • 28

2 Answers2

3

You can use clojure meta-data feature which allows meta data (a map) to be attached to any object that implements IMeta interface (which turns out to be every object as IObj extends IMeta and every object extend IObj)

Now there are 2 options.

1) You can attach the meta data to a var (the var points to the actual IFn object)

(defn hello {:name "hello"} [] 10)

and on Java side you get hold of the var hello and use IMeta methods to get the meta data and detect if your specific meta data is there or not. The problem with this may be that your Java code access/handle IFn objects directly rather than their vars (ex: Anonymous functions), to solve this try the 2nd option.

2) Attach the meta data to the function object itself:

(def hello (with-meta (fn [] 10) {:name "hello"}))

You cannot use defn as that attach meta data to the var. The above sample code attach the meta data to the function object itself. On Java side, typecase the function object to IMeta and do the check. The above code can be made a bit more defn likish with a help of a macro which is left as an exercise :)

Ankur
  • 33,367
  • 2
  • 46
  • 72
  • Thanks! Unfortunately, I don't even have access to the IFn object itself -- only to its class. I need to somehow tag the class (I don't even need to attach any specific information, just a way to determine if the class is "marked" somehow). I thought of tagging it by having the invoke method specify that it throws a well-known checked exception, but there is no way that I know of doing that from Clojure. – pron Apr 10 '13 at 12:44
  • Can you provide some sample code of clojure and java to show how class from clojure are created and accessed from Java as that would make the question more clear – Ankur Apr 10 '13 at 12:46
  • I use a JavaAgent to instrument some classes. I'm notified when a new class is loaded. I'd like to somehow tag a Clojure function so that I'll know if it requires instrumentation. – pron Apr 10 '13 at 12:48
0

It turns out that if you enclose the function body with a let statement containing a local definition, that variable name will appear in the method's local table in the class file. A bit cumbersome, though. Still looking for a better way.

pron
  • 1,693
  • 18
  • 28