web-dev-qa-db-ja.com

Ref、Var、Agent、AtomのClojureの違いと例

私はClojureを初めて使用します。実世界のシナリオについて説明してもらえますか。つまり、Ref、Var、Agent、Atomを使用する場所です。私は本を​​読みましたが、実世界の例を理解できませんでした。

103
user472557

この質問に対する本当の答えとして、「Clojureの喜び」または「Clojureのプログラミング」を強くお勧めします。それぞれの動機の短い切り抜きを再現できます。

アイデンティティの概念に関するこのビデオ および/または ここで勉強する を見ることから始めます。

  • 参照は 調整された同期 「多くのアイデンティティ」へのアクセス。
  • 原子は 調整されていない同期 単一のアイデンティティへのアクセス。
  • エージェントは 調整されていない非同期 単一のアイデンティティへのアクセス。
  • Varはスレッドローカル用 孤立したアイデンティティ 共有デフォルト値を使用します。

調整済み アクセスは、2つのIDを一緒に変更する必要がある場合に使用されます。古典的な例は、1つの銀行口座から別の銀行口座にお金を移動する場合です。

調整されていない 1つのIDのみを更新する必要がある場合にアクセスが使用されます。これは非常に一般的なケースです。

同期 アクセスは、コールが続行する前にすべてのIDが安定するまで待機すると予想される場合に使用されます。

非同期 アクセスは「ファイアアンドフォーゲット」であり、IDが独自の時間で新しい状態に到達できるようにします。

163
Arthur Ulfeldt

参照は、スレッド間で同期する必要がある状態のためのものです。さまざまなものを追跡する必要があり、一度にいくつかのことを書き込む操作を行う必要がある場合は、refsを使用します。状態の複数の異なる部分があるときはいつでも、refを使用することは悪い考えではありません。

アトムは、スレッド間で同期する必要がある独立した状態のためのものです。 atomと他の何かを同時に変更する必要がない場合、at atomを使用すると安全です(特に、プログラム全体で1つの状態のみをアトムに入れることができます。重要な例として、atomはおそらく安全です-状態は関数外のすべてに見えないので、関数内の状態の変化を心配する必要はありません。

エージェントの第一のポイントは、異なるスレッドで実行されることです。エージェントの値を取得し、その値に関数を適用するように指示することはできますが、関数がいつ実行されるか、または関数がどの値に適用されるかはわかりません。

Varは、スレッドごとに何かを保存する必要がある場合に使用します。マルチスレッドプログラムがあり、各スレッドが独自のプライベート状態を必要とする場合、その状態を変数に入れます。

実世界の例に関して言えば、あなたがしようとしていることの例を提供するなら、私たちは何を使うべきかをあなたに伝えることができます。

38
Retief

これらのタイプについて最初に読んだとき、それぞれを使用できる場所または使用する場所を理解するのにも苦労しました。

データが変更されない場合は、varを使用します。これは、defまたはdefのようなdefnで始まるほとんどの関数を使用する場合に発生します。

変更する単一のアイテムがある場合は、atomを使用します。例は、アイテムを追加するカウンターまたはベクトルです。

同時に変更する必要のあるものが2つ以上ある場合は、refを使用します。よく知っているなら、「データベーストランザクション」を考えてください。これの標準的な例は、1つのアカウントから別のアカウントへの送金です。各アカウントをrefに保存して、変更をアトミックに見えるようにすることができます。

何かを変更したいが、いつでも構わないときにエージェントを使用します。これは、長い計算またはファイルまたはソケットに何かを書き込むことがあります。後者ではsend-offを使用する必要があることに注意してください。

注:これらのそれぞれにはさらに多くのものがあることを感謝していますが、これが出発点になることを願っています。

29
optevo

私はそれらの違いを要約して記事を書き、どちらを使用するかを選択するのに役立ちます。

状態の共有-変数、原子、エージェント、参照を使用する場合

このトピックで答えを探している人に役立つことを願っています。

@tunaci提案後の記事からのいくつかのショートカット:

Vars

Varはすべてのスレッドに対してグローバルです。

作成後に変数を変更しないでください。技術的には可能ですが、多くの理由で悪い考えです。

原子

すべてのスレッドの可変状態へのアクセスを共有します。変更は同期的に発生します。実行中に他のスレッドが状態を変更したときに再試行してください。

べき等でない関数および長時間実行される関数を使用しないでください

エージェント

すべてのスレッドの可変状態へのアクセスを共有します。変更は非同期的に発生します。

Refs

Refは、データベーストランザクションと同様に機能します。書き込みと読み取りはdosyncで保護されます。トランザクションで安全に多くの参照を操作できます。

そして、どれを使用するかのフローチャート: flowchart

いくつかの更新は常に可能であるため、ウェブサイトの画像をご覧ください。

コピーと過去の記事なしで完全な答えを出すのは複雑で長いトピックですので、私はあなたをウェブサイトにリダイレクトすることを許してください:)

23
kabra

アトム、参照、エージェント-ここでいくつかのイルミネーション http://blog.jayfields.com/2011/04/clojure-state-management.html

4
Gokul