2011-01-01 13 views

答えて

82

私は全く利用していないので、構造体を効果的に廃止されると考えています。

多くのマップインスタンスで使用されている固定キーセットが固定されている場合、通常はレコードを作成します。大きな利点は次のとおりです。

  • パフォーマンス
  • 生成されたクラスは、私がdefrecord周りに追加のマクロ機械でマルチメソッドまたはその他の状況
  • にオンに切り替えることができますタイプを持って、私はフィールド検証を得ることができ、デフォルト値、および私はほとんどの目的
  • キーとヴァルス用のマップは、(安定にPEを結果を返すよう
  • レコードは、任意のインターフェイスまたはプロトコルを実装することができます(マップはできません)
  • レコードが行動したいものは何でも他のものR-作成)ため

レコードのいくつかの欠点:

  • レコードは、Javaクラスのインスタンス(ないClojureのマップ)であるため、構造的共有はありません同じレコード構造ので、おそらくより多くのメモリを使用します。変更された同等のマップ構造。 JVMは、この種の短命のゴミを特別な汗をかくことなく食べるように設計されていますが、レコードを "変更"するとオブジェクトの作成/破棄も増えます。
  • 開発中にレコードを変更する場合は、REPLを頻繁に再起動して変更を取得する必要があります。これは通常、開発の幅が狭い場合にのみ問題になります。
  • 既存のライブラリの多くは、レコードをサポートするように更新されていません(ポストウォーク、ジップ、マッチャーなど)。必要に応じてこのサポートを追加しました。
+0

あなたの3番目の引数に記述するコンストラクタフォームは、Common Lispが 'defstruct'で定義されたコンサートタイプで使用される引数*の順番で" BOAコンストラクタ " - *を参照するものです。 http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_b.htm#boa_lambda_listを参照してください。 – seh

+0

こんにちはアレックス - 私はあなたがレコードが実際に構造共有を使っていることがわかると思います。彼らは完全な永続的なデータ構造を実装しているので、通常のマップのすべての利点を保ちます。 – mikera

+0

Mikera - レコードは、最終フィールドを持つJavaクラスを生成します。ひとつにまとめることは、新しいJavaオブジェクトを生成する必要があります。フィールドインスタンスは不変なので再利用できますが、通常のClojureマップほど効率的ではありません。 –

9

他の大きな利点の1つは、レコードがあなたがディスパッチできるタイプ(そのクラス)を持っていることです。

この機能を使用していますが、すべての可能な用途の代表ではない例は以下の通りです:

(defprotocol communicate 
    (verbalize [this])) 

(defrecord Cat [hunger-level] 
    communicate 
    (verbalize [this] 
    (apply str (interpose " " (repeat hunger-level "meow"))))) 

(defrecord Dog [mood] 
    communicate 
    (verbalize [this] 
    (case mood 
     :happy "woof" 
     "arf"))) 

(verbalize (->Cat 3)) 
; => "meow meow meow" 

(verbalize (->Dog :happy)) 
; => "woof" 
+1

実際には、タイプだけでなく、どのような関数でもディスパッチすることができます。普通のマップを使って、 "type"という名前のキーを持つ別のエントリを追加することができます。次に、 "type"エントリの値をチェックするディスパッチ関数を使用することができます。 –

+6

@Goran、これはマルチメソッドに適用され、プロトコルを使用すると、タイプ上でのみディスパッチできます。それにもかかわらず、defrecordsを使用している点では、defstructまたはmapが型を自動的に追加しない間に型を暗黙的に追加しています。 – bmillare

+0

この回答は本当に簡潔です。例がいいかもしれません。 – matanster

14

スチュアート・シエラは最近もdefrecordのセクションが含まれている、「Clojureの1.2と式問題の解決」に興味深い記事を書いた:

http://www.ibm.com/developerworks/java/library/j-clojure-protocols/index.html#datatypes

私は全体の記事が良い出発だと思いますプロトコルと記録を理解するためのポイント。

+2

これはリンクのみの回答です。それは少なくとも要約を必要とする。 – MasterMastic

2

ほとんどの場合、マップを使用し、多型性が必要な場合のみ記録します。マップだけでも、マルチメソッドを使用することができます。ただし、プロトコルが必要な場合はレコードが必要です。これを考えると、レコードに頼る前にプロトコルが必要になるまで待ってください。それまでは、より多くのデータ中心の単純なコードを使用することを避けてください。

0

パフォーマンスの面で一般的に同等以上であることに加えて、同じプログラミングインターフェイスをマップとして公開することに加えて、レコードは軽い構造を強制します。キー名とキー数が強制されます定義時に。これは、同じ構造が多くの値から期待される場合(または、人工的に他の方法では堅牢でない場合)、ばかげたエラーを避けるのに役立ちます。

本来の動機が何であれ、このプロパティも地図から離れています。

関連する問題