Если вы не можете определить класс (возможно, программно в макросе) во время компиляции, вам нужно прибегнуть к использованию отражения.Это будет делать то же самое, что и eval, когда он пытается скомпилировать код.См. clojure.lang.Reflector/invokeStaticMethod
: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Reflector.java#L198
(import 'clojure.lang.Reflector)
;; Here, you can pass *any string you have at runtime*
(Reflector/invokeStaticMethod Integer "parseInt" (into-array ["1"]))
Это может использоваться произвольно во время выполнения, поскольку это не макрос или специальная форма.Например, имя метода может быть задано пользователем через графический интерфейс или через сокет во время выполнения.
Если у вас есть имя класса во время компиляции, вы можете использовать макрос, как предложил Николас,Однако нет необходимости создавать код, похожий на (Integer/parseInt "1")
, поскольку это просто синтаксический сахар для более базовой (и дружественной к макросам) .
специальной формы: (. Integer parseInt "1")
.
;; Here, the method name needs to be a *string literal*
(defmacro static-call
"Takes a Class object, a string naming a static method of it
and invokes the static method with the name on the class with
args as the arguments."
[class method & args]
`(. ~class ~(symbol method) ~@args))
Однако,единственная «настоящая работа», которую выполняет этот макрос, - преобразовать строку в символ.Вы, вероятно, просто использовали бы специальную форму .
во внешнем макросе (тот, который каким-то образом получает имена методов, например, получая те, которые передаются в качестве аргументов, или читая их из var или из файла конфигурации).
;; Use ordinary Clojure functions to construct this
(def the-static-methods {:foo ["Integer" "parseInt"], :bar ["Long" "parseLong"]})
;; Macros have access to all previously defined values
(defmacro generate-defns []
(cons `do (for [[name-keyword [class-string method-string]] the-static-methods]
`(defn ~(symbol (name name-keyword)) [x#]
(. ~(symbol class-string) ~(symbol method-string) x#)))))
(generate-defns)