Clojure:动态导入java类

时间:2013-10-08 19:42:49

标签: java clojure

假设我定义了这样的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类?如果是这样的话?谢谢!

1 个答案:

答案 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))))

可能有一种更清洁的方式,如果我找到答案,我会更新这个答案。