1. ホーム
  2. clojure

[解決済み] Clojureのフューチャーとプロミスはどう違うのか?

2023-03-15 04:15:33

質問

先物もプロミスも値を計算するまでブロックされますが、両者の違いは何でしょうか?

どのように解決するのですか?

Clojureの用語で答えると、次のような例があります。 Sean Devlinのスクリーンキャスト :

(def a-promise (promise))
(deliver a-promise :fred)

(def f (future (some-sexp)))
(deref f)

約束の中で、後の計算で選択する値を明示的に渡していることに注意してください ( :fred この場合)。 一方、未来は作成された場所で消費されます。 そのため some-expr はおそらく裏で起動され、(最終的には)同時に計算されますが、アクセスされるまでに評価されないままであれば、スレッドはそれが利用可能になるまでブロックされます。


を追加するために編集されました。

約束と未来の区別をさらにつけるために、次のことに注意しましょう。

約束

  1. を作成すると promise . そのプロミスオブジェクトは、これで任意のスレッドに渡すことができます。
  2. あなたは計算を続けます。 これらは,副作用,データのダウンロード,ユーザ入力,データベースアクセス,他のプロミスなどを含む非常に複雑な計算をすることができます -- お好きなように。 コードはどのプログラムでもメインラインのコードとほとんど同じように見えるでしょう。
  3. 終了したら、次のことができます。 deliver を実行し、その結果をそのプロミスオブジェクトに渡します。
  4. を試行するすべての項目は deref を試みるアイテムは、計算が終了するまでブロックされます。 いったん計算が終わって deliver を編集すると、プロミスはそれ以上ブロックされません。

未来

  1. あなたの未来を創るのはあなたです。 あなたの未来の一部は、計算のための表現です。
  2. 未来は同時に実行されるかもしれませんし、されないかもしれません。 スレッドが割り当てられ、プールから割り当てられるかもしれません。 何もせずに待つこともできます。 あなたの視点から を伝えることはできません。 .
  3. ある時点で、あなた (または別のスレッド) は deref が未来を計算します。 もし計算が既に終了していれば、その結果を取得する。 まだ完了していない場合は、完了するまでブロックする。 (おそらくまだ始まっていない場合。 deref を実行し始めることを意味すると思われるが、これも保証されない)。

あなたが ができた はプロミスの生成に続くコードと同じくらい複雑な式を作ることができますが、それが望ましいかどうかは疑問です。 つまり,futureはバックグラウンドで素早く計算するのに向いていて,promiseは大規模で複雑な実行経路に向いているのです. また,プロミスは,利用可能な計算という点では,プロミス作成者が仕事をし,別のスレッドが収穫を得るという方向性で,もう少し柔軟性があるように思われます. Futuresは自動的にスレッドを開始し(醜くエラーを起こしやすいオーバーヘッドなしで)、あなた(開始したスレッド)が結果を必要とするまで他のことを続けることをより指向しています。