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