Suppose I define such clojure function:
(defn print-this [this] (println "print this: " this))
If I use the function in repl:
(print-this that)
I would end up with:
print this: that
nil
as output.
Now if I make such definition:
(defn import-by-name [name] (import (some.package.value name)))
and use the function in repl:
(import-by-name "SomeClassName")
I get
java.lang.ClassNotFoundException: some.package.value.name (NO_SOURCE_FILE:0)
where I would expect that "name" be replaced by "SomeClassName" instead. If I type:
(import (some.package.value SomeClassName))
everything works as expected.
Why is it that [name] is not interpreted in the import-by-name function above? Is it possible to dynamically import a java class from a variable value? If so how? thanks!
import
is a macro, so any symbols you pass to it will be taken literally.
(macroexpand '(import (some.package.value name)))
;; => (do (clojure.core/import* "some.package.value.name"))
Literals
For string literals, and by extension collection literals, you can use a macro to accomplish what you are describing.
(defmacro import-by-name [name] `(import '[some.package.value ~name]))
(import-by-name "ClassName") ;; => nil
Vars
For importing classes from a var, you have to start dipping into the internals of namespaces.
(defn import-by-name [n]
(.importClass (the-ns *ns*)
(clojure.lang.RT/classForName (str "some.package.value." n))))
There might be a cleaner way, and I will update this answer if I find one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With