2016-05-05 10 views
9

私はの機能をClojureで理解できませんでした。 クロージャーでは何を使用していますか?Clojureには何がありますか?

例を教えてください。

+0

は、ドキュメントページ上の例は心から歓迎があります:https://clojuredocs.org/clojure.core/reify – OlegTheCat

答えて

15

reifyマクロjava.lang.Objectクラスを拡張する匿名クラスを作成したり、指定されたインターフェイス/プロトコルを実装したりできます。 API docsは目的をはっきりと説明するのではなく、マクロが何をするのかという技術的な詳細を提供します。 、具体化のClojure 1.2のよう

も インターフェイスを実装するために利用可能である:Java interop documentationは、目的の簡単な説明を提供します。

さらに多くの情報がdatatypes documentatioで見つけることができるのnあなたはそれが何を非常に詳細な説明を見つけることができますし、それはproxyと比較する方法場所:defrecordのDeftypeとは、名前付きの型を定義する定義を具体化しながら

両方 匿名型を作成し、その型のインスタンスを作成します。ユースケースは で、1つ以上のプロトコルまたは インターフェイスの1回限りの実装が必要であり、ローカルコンテキストを利用したいと考えています。 では、プロキシに似たユースケース、またはJavaの匿名の内部クラス です。

reifyのメソッド本体はレキシカルクロージャであり、ローカルスコープを囲む を参照できます。 Reefはプロキシとは異なります。

プロトコルまたはインターフェイスのみがサポートされています。具体的なスーパークラスはありません。 メソッド本体は、 外部fnsではなく、結果のクラスの真のメソッドです。インスタンス上のメソッドの呼び出しは、マップルックアップを使用して ではなく直接実行されます。 メソッドマップ内のメソッドの動的スワップはサポートされていません。結果は、 の構築と呼び出しの両方で、プロキシより優れたパフォーマンスです。すべての場合においてreifyはプロキシよりも好ましいです。 その制約は厳しいものではありません。

+0

'reify'でクラス(' Object'以外)を拡張することはできませんので、最初の文は少し間違っています。 –

+0

@ NathanDavisはい、そうです。 –

24

reifydefnに何であるかfndefrecordにあります。
簡単に言えば

「右ああ......そうreifyを何だ」、プロトコルは、データ型がサポートする機能、レコードのリストは、データ型がされており、reificationsは匿名のデータ型です。

reifyは、プロトコルとタイプ/レコードを理解することなく具体的​​には理解できません。プロトコルは、異なる引数が与えられたときに実際に異なる動作をするconjなどの関数に同じ名前を使用する方法です((conj [:b :c] :a) => [:b :c :a],)。レコードはオブジェクトやタイプに似ています(ただし、それらはマップのように機能して、それらはより大きなものになります)。

もっと根本的に、目標は、に能力がシームレスに既存の機能で動作する新しいタイプのデータ、および既存のデータとシームレスに連携し、新たな機能を追加することです「式の問題」を解決することです。

だから、ある日、あなたは自分自身に言う。「自己、あなたはアヒルであることが何であるかを学ばなければならない!あなたは、プロトコル記述:

(defprotocol Quacks 
    (quack [_] "should say something in ducky fashion")) 

をしかし、それはあなたがそれ 'IFY 本当' をあまりにも抽象的です:

(def donald (reify Quacks 
        (quack [_] "Quacks and says I'm Donald"))) 

さて、最後に、あなたの創造を体験することができます。

(quack donald) => "Quacks and says I'm Donald" 

あなたはダフィーについて覚えています:

(def daffy (reify Quacks 
        (quack [_] (str "Quacks and says I'm Daffy")))) 

(quack daffy) => "Quacks and says I'm Daffy" 

しかし、あなたはヒューイについて覚え時間によって、あなたは間違いを実現し、アヒルは再利用可能な方法であるかを定義:

(defrecord Duck [name] 
    Quacks 
    (quack [_] (str "Quacks and says I'm " name))) 

とはnewアヒルを作る(それを行うには、いくつかの方法があります):

(:name huey) => "Huey" 

をしかし、その後、あなたはカモであることを覚えている:レコードがマップのように振る舞うことを

(def huey (->Duck "Huey")) 
(def duey (Duck. "Duey")) 
(def louie (new Duck "Louie")) 

(quack huey) => "Quacks and says I'm Huey" 

覚えておいてください(!プロトコルに感謝)

(defprotocol Walks 
    (walk [_] "should walk like a duck")) 

と鴨

(extend-type Duck 
    Walks 
    (walk [_] "waddle waddle")) 

(walk louie) => "waddle waddle" 

の定義を拡張今、私たちは(同じことを教える同じプロトコルを実装するために、他のタイプを拡張することができます:あなたは別のプロトコルを書くいんちき、ので、唯一のものではありませんどのように他のもので動作するように機能):

それでは、私たちはプログラマが

(defrecord Programmer [] Quacks 
    (quack [_] "Monads are simply monoids in a category of endofunctors...")) 

(quack (Programmer.)) => "Monads are simply monoids in a category of endofunctors..." 
:-)あまりにもいんちきしたいとしましょう

私はこの偉大なことをお勧めしますexplanation of protocolsexplanation of reifychapter on protocols in "Clojure for the Brave and True"です。

免責事項:これは、どのプロトコルが使用されているかを最初に理解することを目的としており、ではなく、のベストプラクティスです。 "Psst!昨日まで自分のプロトコル/インターフェースを実際に書いたことがなかったので、私はこの質問に主に答えました。 !だから

私はそれが他の誰かの学習を強化することを願っていながら、私は批判や編集の提案」

関連する問題