1

2 つのオブジェクト (この場合はレコード) が定義されているとします。

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

そして、これらの2つのレコードが(インスタンス化されていない)リストにあります:

(def recs [rec1 rec2])

リスト内のこれら 2 つのレコードをインスタンス化する最良の方法は?

以下は例外を与える

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

new とドット コンストラクターはクラス名シンボルを想定しているためです。では、これについて最善の方法は何ですか?これまでのところ、リフレクションが唯一の方法のようです。

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

これは、オブジェクトでコンストラクターを呼び出すという一見単純なタスクを実行するための、非常に醜い (そして遅い) 方法のように思えます。それでは、正しい(または慣用的な)方法は何ですか?

4

1 に答える 1

2

あなたの質問は私には明確ではありませんが、ここにいくつかの観察があります:

  • rec1 と rec2 は同じタイプの異なる ctor ではなく、それぞれ 1 つの ctor を持つ別のタイプです (偶然にも、2 つの ctor は同じアリティ/シグネチャを持っています)。
  • あなたの「根拠のないリスト」は意味がありません。
  • 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})
于 2012-04-23T22:14:26.567 に答える