我有一系列记录/类,我map
在new
的序列上,期望获得这些记录/类的一系列实例。我知道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])
此外,我正在寻找更优雅的东西。
答案 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])
这可能会导致反射的性能问题,因此基于宏的解决方案优先于此。