一流的类/记录实例化

时间:2012-06-01 20:13:49

标签: clojure

我有一系列记录/类,我mapnew的序列上,期望获得这些记录/类的一系列实例。我知道new是一种特殊的形式,但在这种情况下我期待Clojure做正确的事。

但这不起作用:

(map new [SomeClass1 SomeClass2 SomeClass3])

这两者都没有。

(map #(new %) [SomeClass1 SomeClass2 SomeClass3])

类似的代码适用于Factor

{ SomeClass1 SomeClass2 SomeClass3 } [ new ] map

在Clojure中这样做的正确方法是什么? (我希望它不会涉及Class.newInstance丑陋。)

修改

以下工作,但可能比必要的慢。 (我不确定。我希望得到一些相关信息。)

(map #(eval `(new ~%)) [SomeClass1 SomeClass2 SomeClass3])

此外,我正在寻找更优雅的东西。

2 个答案:

答案 0 :(得分:3)

因为特殊形式很好......特殊的它们不是一流的而且不像正确的函数那样构成,你可以用eval和宏来解决这个问题:

使用eval的解决方案:

(defn fnew [c] (eval `(new ~c))) 
hello.core> (map fnew ['Exception 'java.lang.String])
(#<Exception java.lang.Exception> "")

和一个带有构造函数参数的版本:

(defn fnew [c] (eval `(new ~@c))) 

hello.core> (map fnew ['(Exception) '(java.lang.String "I am a contructor argument")])
(#<Exception java.lang.Exception> "I am a contructor argument")

(map fnew [ [Exception] [(class "foo") "I am a contructor argument"]])
(#<Exception java.lang.Exception> "I am a contructor argument")

这是一个宏示例

hello.core> (defmacro newify [classes] (apply vector (for [c classes] `(new ~c))))
#'hello.core/newify

hello.core> (macroexpand '(newify [java.lang.String Exception]))
[(new java.lang.String) (new Exception)]

hello.core>  (newify [java.lang.String Exception])
["" #<Exception java.lang.Exception>]

宏版本可能更有效,而eval版本更灵活。

答案 1 :(得分:1)

由于new是一种特殊形式,使其像第一类一样工作的解决方案之一是使用clojure低级调用,如:

(map #(clojure.lang.Reflector/invokeConstructor %1 (into-array [])) [String])

这可能会导致反射的性能问题,因此基于宏的解决方案优先于此。