2013-04-10 12 views
8

Ho bisogno di taggare alcune funzioni di Clojure come "speciali" in modo che il codice Java possa riconoscerle come tali utilizzando il reflection. Ho provato ad aggiungere un'annotazione a una funzione, ma a quanto pare non è supportata. Ho provato a reify un'interfaccia che estende IFn (in modo che il codice Java possa riconoscere l'oggetto funzione), ma non va bene perché Clojure non utilizza direttamente il metodo reificato come codice che implementa invoke, ma piuttosto una chiamata indiretta a un Afunction oggetto che sta effettivamente implementando il metodo (ho bisogno di taggare il vero metodo invoke con il codice della funzione effettiva).Come taggare una funzione Clojure in modo che potessi riconoscerla con Java reflection

Qualche idea?

EDIT: anche la codifica in un modo che potrebbe essere raggiunto con la libreria ASM (invece di riflessione regolare) andrebbe bene, ma ho bisogno di codificare in qualche modo l'oggetto reale AFunction o il metodo invoke. Inoltre, non posso accedere all'oggetto reale AFunction - Ho bisogno che il tag sia visibile sulla classe.

risposta

3

È possibile utilizzare la funzione di meta-dati clojure che permette ai meta dati (una mappa) per essere collegato a qualsiasi oggetto che implementa IMeta interfaccia (che si rivela essere ogni oggetto come IObj estende Imeta e ogni oggetto estendere IObj)

Ora ci sono 2 opzioni.

1) È possibile collegare i meta-dati per una var (i punti Var l'oggetto reale IFN)

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

e sul lato Java entrare in possesso di var ciao e utilizzare metodi Imeta per ottenere il metadati e rileva se i tuoi metadati specifici sono presenti o meno. Il problema con questo può essere che il tuo codice Java accede/gestisce direttamente gli oggetti IFn piuttosto che i loro vars (es: funzioni anonime), per risolvere questo prova la seconda opzione.

2) Collegare i meta-dati per l'oggetto funzione stessa:

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

Non è possibile utilizzare defn come che si attaccano i metadati al var. Il suddetto codice di esempio associa i metadati all'oggetto funzione stesso. Sul lato Java, digitare l'oggetto funzione su IMeta ed eseguire il controllo. Il codice sopra può essere reso un po 'più defn likish con l'aiuto di una macro lasciata come esercizio :)

+0

Grazie! Sfortunatamente, non ho nemmeno accesso all'oggetto IFn stesso, solo alla sua classe. Ho bisogno di taggare in qualche modo la classe (non ho nemmeno bisogno di allegare informazioni specifiche, solo un modo per determinare se la classe è "contrassegnata" in qualche modo). Ho pensato di etichettarlo facendo in modo che il metodo invoke specificasse che genera un'eccezione ben conosciuta, ma non c'è modo che io sappia farlo da Clojure. – pron

+0

Puoi fornire alcuni esempi di codice di clojure e java per mostrare come vengono create le classi da clojure e accedute da Java in quanto ciò renderebbe la domanda più chiara – Ankur

+0

Uso un JavaAgent per lo strumento di alcune classi. Mi viene notificato quando viene caricata una nuova classe. Mi piacerebbe in qualche modo taggare una funzione Clojure in modo che possa sapere se è necessaria la strumentazione. – pron

0

Si scopre che se si racchiude il corpo della funzione con un'istruzione let che contiene una definizione locale, quella il nome della variabile verrà visualizzato nella tabella locale del metodo nel file di classe. Un po 'macchinoso, però. Sto ancora cercando un modo migliore.

Problemi correlati