Here’s an extract from a REPL session that hopefully explains what I want to achieve:
user> (Integer/parseInt "1")
1
user> (def y Integer)
#'user/y
user> (y/parseInt "1")
No such namespace: y
[Thrown class java.lang.Exception]
How can I access static method/fields of a Java class using a non-Classname, user defined symbol?
UPDATE
The following works as expected:
user> (eval (list (symbol (.getName y) "parseInt") "1"))
1
Is there a better/more idiomatic way to achieve the same result?
If you cannot determine the class (possibly programmatically in a macro) during compile time, you need to resort to use reflection. This would do the same thing as eval does when it tries to compile the code. See
clojure.lang.Reflector/invokeStaticMethod: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Reflector.java#L198This can be used in arbitrary ways at runtime, since it’s not a macro or a special form. For example, the name of the method could be given by the user via a GUI or though a socket at runtime.
If you have the name of the class at compile time, you can use a macro as Nicolas suggested. However, it’s unnecessary to construct the code to look like
(Integer/parseInt "1"), since it’s just syntactic sugar for the more basic (and macro friendly).special form:(. Integer parseInt "1").However, the only “real work” this macro performs is to convert the string into a symbol. You would probably just use the
.special form in an outer macro (the one that acquires the names of the methods somehow, e.g. by getting those passed as arguments, or by reading them from a var or from a configuration file).