Как мне пометить функцию Clojure, чтобы я мог распознать ее с помощью отражения Java

Мне нужно каким-то образом пометить определенные функции Clojure как «специальные», чтобы код Java мог распознавать их как таковые с помощью отражения. Я пытался добавить аннотацию к функции, но, видимо, это не поддерживается. Я пытался reify расширить интерфейс IFn (чтобы код Java мог распознавать объект функции), но это бесполезно, потому что Clojure не использует материализованный метод напрямую в качестве кода, реализующего invoke, а использует косвенный вызов объекта-функции. Afunction, который фактически реализует метод (мне нужно пометить фактический метод invoke фактическим кодом функции).

Есть идеи?

РЕДАКТИРОВАТЬ: даже пометка способом, к которому можно получить доступ с помощью библиотеки ASM (а не с обычным отражением), будет в порядке, но мне нужно как-то пометить фактический объект AFunction или метод invoke. Кроме того, я не могу получить доступ к фактическому объекту AFunction — мне нужно, чтобы тег был виден в классе.


person pron    schedule 10.04.2013    source источник


Ответы (2)


Вы можете использовать функцию метаданных clojure, которая позволяет прикреплять метаданные (карту) к любому объекту, который реализует IMeta интерфейс (который оказывается каждым объектом, поскольку IObj расширяет IMeta, а каждый объект расширяет IObj)

Теперь есть 2 варианта.

1) Вы можете прикрепить метаданные к var (var указывает на фактический объект IFn)

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

а на стороне Java вы получаете var hello и используете методы IMeta для получения метаданных и определения, есть ли ваши конкретные метаданные или нет. Проблема может заключаться в том, что ваш Java-код обращается/обрабатывает объекты IFn напрямую, а не их переменные (например, анонимные функции), чтобы решить эту проблему, попробуйте второй вариант.

2) Прикрепите метаданные к самому объекту функции:

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

Вы не можете использовать defn для присоединения метаданных к var. Приведенный выше пример кода прикрепляет метаданные к самому объекту функции. На стороне Java введите объект функции в IMeta и выполните проверку. Приведенный выше код можно сделать немного более defn симпатичным с помощью макроса, который оставлен в качестве упражнения :)

person Ankur    schedule 10.04.2013
comment
Спасибо! К сожалению, у меня нет доступа даже к самому объекту IFn — только к его классу. Мне нужно как-то пометить класс (мне даже не нужно прикреплять какую-то конкретную информацию, просто способ определить, помечен ли класс как-то). Я думал пометить его, указав в методе вызова, что он выдает хорошо известное проверенное исключение, но я не знаю способа сделать это из Clojure. - person pron; 10.04.2013
comment
Можете ли вы предоставить пример кода clojure и java, чтобы показать, как класс из clojure создается и доступен из Java, поскольку это сделало бы вопрос более ясным. - person Ankur; 10.04.2013
comment
Я использую JavaAgent для инструментовки некоторых классов. Я получаю уведомление, когда загружается новый класс. Я хотел бы как-то пометить функцию Clojure, чтобы знать, требует ли она инструментовки. - person pron; 10.04.2013

Оказывается, если вы заключите тело функции с оператором let, содержащим локальное определение, это имя переменной появится в локальной таблице метода в файле класса. Хотя немного громоздко. Все еще ищет лучший способ.

person pron    schedule 10.04.2013