6

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!

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Just be aware, there are limits. Passing it a string works, but passing it a var will just append the symbol. I'm not sure what exactly you are trying to do.
Is there anyway to do a similar thing with a var? The goal is to interface clojure code with a large xjc-generated java library from a fairly complex xsd.
Are you trying to implement the equivalent of import some.package.*, or are you reading this list from a file?
No. It could be list from a file or a command-line argument. I want to import a small subset of classes from some.package.value but specify from input (file or command line). Thanks!
I've updated my answer to include an attempt at your scenario. Let me know if it works for you.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.