如何创建记录的新实例?

时间:2012-04-23 21:58:32

标签: clojure

鉴于我定义了两个对象(在本例中为记录):

(defrecord rec1 [one two])
(defrecord rec2 [one two])

我在列表中列出了(未经证实的)这两个记录:

(def recs [rec1 rec2])

如何在列表中实现这两个记录的最佳方式?

以下是一个例外

(map (fn [rec] (rec. 1 2)) recs)

因为new和点构造函数需要classname-symbol。那么最好的方法是什么呢?到目前为止反射似乎是唯一的方法:

(map #(clojure.lang.Reflector/invokeConstructor % (to-array [1 2 3])) recs)

这似乎是一种过于丑陋(和缓慢)的方式来执行在对象上调用构造函数的看似简单的任务。那么正确的(或惯用的)方式是什么?

1 个答案:

答案 0 :(得分:2)

我的问题不明确,但这里有一些观察:

  • rec1和rec2不是同一类型的不同ctors,而是每个有1 ctor的独立类型(同时两个ctor具有相同的arity /签名)
  • 你的'未实例列表'没有意义。
  • defrecord为这个用途生成了一些辅助函数......

我不确定你要做什么,这里有一些例子可以澄清你的要求......

(def r1 (->rec1 1 2))
;=> #user.rec1{:one 1, :two 2}

(def c1 (rec1. 1 2))
;=> #user.rec1{:one 1, :two 2}

(def m1 (map->rec1 {:one 1 :two 2}))
;=> #user.rec1{:one 1, :two 2}

(def r2 (->rec2 1 2))
;=> #user.rec2{:one 1, :two 2}

(def c2 (rec2. 1 2))
;=> #user.rec2{:one 1, :two 2}

(def recs [(rec1. 1 2) (->rec1 1 2)])

(for [[n m] (partition 2 (range 4))] (->rec1 n m))
;=> (#user.rec1{:one 0, :two 1} #user.rec1{:one 2, :two 3})