Я несколько дней изучаю Clojure и у меня возникают некоторые проблемы с прорезыванием зубов, поэтому я прошу совета.
Я пытаюсь сохранить класс Java в переменной Clojure и вызывать его статические методы, но он не работает.
Пример:
user=> (. java.lang.reflect.Modifier isPrivate 1)
false
user=> (def jmod java.lang.reflect.Modifier)
#'user/jmod
user=> (. jmod isPrivate 1)
java.lang.IllegalArgumentException: No matching method found: isPrivate for class java.lang.Class (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:4543)
Из этого исключения похоже, что среда выполнения ожидает, что переменная будет содержать объект, поэтому она вызывает .getClass (), чтобы получить класс, и ищет метод, используя отражение. В этом случае переменная уже содержит класс, поэтому .getClass()
возвращает java.lang.Class
, и поиск метода явно завершается неудачей.
Есть ли способ обойти это, кроме написания моего собственного макроса?
В общем случае я хотел бы иметь объект или класс в переменной и вызывать для него соответствующие методы - типизацию утки как для статических, так и для экземпляров методов.
В этом конкретном случае я просто хотел бы более короткое имя для java.lang.reflect.Modifier
, если хотите, псевдоним. Я знаю о import
, но ищу что-то более общее, например, псевдоним пространства имен Clojure, но для классов Java. Есть ли другие механизмы для этого?
Edit:
Может быть, я просто запутался в соглашениях о вызовах здесь. Я думал, что модель Lisp (и, соответственно, Clojure) должна была оценить все аргументы и вызвать первый элемент в списке как функцию.
В этом случае (= jmod java.lang.reflect.Modifier)
возвращает true, а (.getName jmod)
и (.getName java.lang.reflect.Modifier)
оба возвращают одну и ту же строку.
Таким образом, переменная и имя класса однозначно оценивают одно и то же, но их все равно нельзя вызывать одинаково. Что здесь происходит?
Редактировать 2
Отвечая на мой второй вопрос (что здесь происходит), доктор Clojure говорит, что
Если первый операнд является символом,
разрешает имя класса, доступ
считается статическим членом
именованного класса ... В противном случае это
предполагается, что является экземпляром
http://clojure.org/java_interop в разделе "Форма Dot"
«Преобразование в имя класса», очевидно, не то же самое, что «вычисление чего-то, что разрешается в имя класса», поэтому то, что я пытаюсь сделать здесь, не поддерживается специальной формой точка.