web-dev-qa-db-ja.com

Clojureでクラスを定義する方法が1つではなく5つあるのはなぜですか?

Clojureには、gen-class、reify、proxy、さらにdeftypeとdefrecordがあり、新しいクラスのようなデータ型を定義します。構文の単純さを重視し、不必要な複雑さを嫌う言語の場合、それは異常なようです。なぜそうなのか誰かが説明できますか?一般的なLISPスタイルのdefclassで十分ですか?

82
Salil

これは、3つの異なる要因の組み合わせです。

  1. JVMの特定の型システム
  2. 型を定義するときのさまざまなユースケースのわずかに異なるセマンティクスの必要性
  3. 言語の進化に伴い、これらの一部は以前に開発され、一部は後で開発されたという事実。

まず、これらが何をするかを考えてみましょう。 deftypegen-classは、どちらも名前付き事前コンパイル用のクラス。 Gen-classが最初に来て、その後clojure 1.2のdeftypeが続きました。 Deftypeが推奨され、パフォーマンス特性は優れていますが、より制限的です。 deftypeクラスはインターフェイスに準拠できますが、別のクラスから継承することはできません。

Reifyproxyの両方を使用して、匿名のインスタンスが動的に作成されます実行時のクラス。プロキシが最初に来て、reifyはclojure 1.2のdeftypeとdefrecordと一緒に来ました。 deftypeと同様に、意味が制限されないReifyが推奨されます。

同時に出現したdeftypeとdefrecordの両方がなぜ同じような役割を果たしているのか、という疑問が残ります。ほとんどの目的のために、私たちはdefrecordを使用したいと思います。それは、私たちが知っており、愛しているさまざまなクロジュールの良さ、順序性などを備えています。 Deftypeは、他のデータ構造を実装するための低レベルのビルディングブロックとして使用することを目的としています。通常のclojureインターフェースは含まれていませんが、可変フィールドのオプションがあります(これはデフォルトではありません)。

さらに読むためにチェックアウト:

clojure.orgデータ型のページ

deftypeとreifyが導入されたGoogleグループスレッド

88
Rob Lachlan

簡単に言えば、それらにはすべて異なる有用な目的があるということです。複雑なのは、基盤となるJVMのさまざまな機能と効果的に相互運用する必要があるためです。

Java interopが必要ない場合は、99%の確率でいずれかのdefrecordを使用することをお勧めしますまたは単純なClojureマップ。

  • プロトコルを使用する場合は、defrecordを使用します
  • それ以外の場合、通常のClojureマップはおそらく最も単純で最も理解しやすい

ニーズがより複雑な場合、次のフローチャートは、これらのオプションの1つを他のオプションよりも選択する理由を説明するための優れたツールです。

http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

Flowchart for choosing the right clojure type definition form

51
mikera