假设我定义了这样的clojure函数:
(defn print-this [this] (println "print this: " this))
如果我在repl中使用该功能:
(print-this that)
我最终会:
print this: that
nil
作为输出。
现在,如果我做出这样的定义:
(defn import-by-name [name] (import (some.package.value name)))
并使用repl中的函数:
(import-by-name "SomeClassName")
我得到了
java.lang.ClassNotFoundException: some.package.value.name (NO_SOURCE_FILE:0)
我希望将“name”替换为“SomeClassName”。如果我输入:
(import (some.package.value SomeClassName))
一切都按预期工作。
为什么在上面的import-by-name函数中没有解释[name]? 是否可以从变量值动态导入java类?如果是这样的话?谢谢!
答案 0 :(得分:5)
import
是一个宏,因此传递给它的任何符号都将按字面意思理解。
(macroexpand '(import (some.package.value name)))
;; => (do (clojure.core/import* "some.package.value.name"))
<强>字面强>
对于字符串文字和扩展集合文字,您可以使用宏来完成您所描述的内容。
(defmacro import-by-name [name] `(import '[some.package.value ~name]))
(import-by-name "ClassName") ;; => nil
<强>瓦尔强>
要从var导入类,您必须开始深入到名称空间的内部。
(defn import-by-name [n]
(.importClass (the-ns *ns*)
(clojure.lang.RT/classForName (str "some.package.value." n))))
可能有一种更清洁的方式,如果我找到答案,我会更新这个答案。