Clojure には、gen-class、reify、proxy、さらに deftype と defrecord があり、新しいクラスのようなデータ型を定義します。構文の単純さを重視し、不必要な複雑さを嫌う言語にとって、それは異常のように思えます。誰かがなぜそうなのか説明できますか?Common Lisp スタイルの defclass で十分でしたか?
2 に答える
これは、次の 3 つの異なる要因の組み合わせです。
- jvm の特定の型システム
- 型を定義するときのユースケースごとにわずかに異なるセマンティクスの必要性
- 言語が進化するにつれて、これらのいくつかは以前に開発され、いくつかは後で開発されたという事実。
まず、これらが何をするのかを考えてみましょう。 deftypeとgen-classは、どちらも事前コンパイル用の名前付きクラスを定義するという点で似ています。gen-class が最初に登場し、続いて clojure 1.2 の deftype が登場しました。Deftype が推奨され、より優れたパフォーマンス特性を備えていますが、より制限的です。deftype クラスはインターフェイスに準拠できますが、別のクラスから継承することはできません。
Reifyとプロキシは両方とも、実行時に匿名クラスのインスタンスを動的に作成するために使用されます。Proxy が最初に登場し、reify は clojure 1.2 で deftype および defrecord とともに登場しました。セマンティクスがあまり制限されていない場合は、deftype と同様に Reify が優先されます。
なぜ deftype と defrecord の両方が同時に出現し、同様の役割を持っているのかという疑問が残ります。ほとんどの目的で、defrecord を使用したいと思うでしょう。これには、私たちが知っていて愛しているさまざまな clojure の利点、seqability などがあります。Deftype は、他のデータ構造を実装するための低レベルのビルディング ブロックとして使用することを目的としています。通常の clojure インターフェイスは含まれていませんが、可変フィールドのオプションがあります (ただし、これはデフォルトではありません)。
さらに読むには、以下をチェックしてください。
簡単に言えば、それらはすべて異なる有用な目的を持っているということです。複雑なのは、基盤となる JVM のさまざまな機能と効果的に相互運用する必要があるためです。
Java との相互運用が必要ない場合は、99% の確率で、defrecord または単純な Clojure マップのいずれかを使用することをお勧めします。
- プロトコルを使用する場合は、defrecord を使用します
- それ以外の場合は、通常の Clojure マップがおそらく最も単純で理解しやすいでしょう。
ニーズがより複雑な場合、次のフローチャートは、これらのオプションのいずれかを他のオプションよりも選択する理由を説明するための優れたツールです。
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/