6

假设我定义了这样的 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)

我希望将“名称”替换为“SomeClassName”。如果我输入:

(import (some.package.value SomeClassName))

一切都按预期工作。

为什么在上面的按名称导入函数中没有解释 [name]?是否可以从变量值动态导入 java 类?如果有怎么办?谢谢!

4

1 回答 1

6

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

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

于 2013-10-08T19:55:35.973 回答