Clojureの将来と約束はどのように異なりますか?


86

フューチャーとプロミスはどちらも、値を計算するまでブロックされます。では、両者の違いは何ですか?


8
なぜ質問に-1が付いているのかわかりませんか、それとも今悪いことを尋ねる前に答えがわからない質問ですか?
ちょうど私の正しい意見2011年

私は答えのどれも-1しませんでしたか?誰が質問または回答に-1を付けたかをどのように知ることができますか?
appshare.co 2011年

あなたと私はできません、Zubair。質問するのは完全に合理的な質問であり、SOにとって間違いなく話題になっていることを考えると、誰があなたの質問に-1を付けたのか興味があります。
ちょうど私の正しい意見2011年

回答:


54

Clojureの用語で答えると、SeanDevlinのスクリーンキャストからのいくつかの例があります。

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

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

promiseでは、後の計算(:fredこの場合)で選択した値を明示的に提供していることに注意してください。一方、未来はそれが作成されたのと同じ場所で消費されています。some-exprおそらく舞台裏立ち上げ、タンデム(最終的に)で計算され、それは、時間によって評価されないままであれば、それが利用可能になるまでには、スレッドブロックをアクセスされています。


追加するために編集

約束と未来をさらに区別するために、次の点に注意してください。

約束する

  1. を作成しpromiseます。そのpromiseオブジェクトを任意のスレッドに渡すことができるようになりました。
  2. 計算を続けます。これらは、副作用、データのダウンロード、ユーザー入力、データベースアクセス、その他の約束など、非常に複雑な計算になる可能性があります。コードは、どのプログラムのメインラインコードにも非常によく似ています。
  3. 終了したら、deliverそのpromiseオブジェクトに結果を表示できます。
  4. deref計算が完了する前に約束をしようとするアイテムは、完了するまでブロックされます。完了しdeliverてプロミスを実行すると、プロミスはブロックされなくなります。

未来

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

将来、promiseの作成に続くコードと同じくらい複雑な式を作成することはできます、それが望ましいかどうかは疑わしいです。つまり、先物は迅速でバックグラウンド可能な計算に非常に適していますが、promiseは大規模で複雑な実行パスに非常に適しています。あまりにも、利用可能な計算の観点から、約束はもう少し柔軟で、仕事をしている約束の作成者と収穫を刈り取る別のスレッドに向けられているようです。先物は、スレッドを自動的に開始し(醜くエラーが発生しやすいオーバーヘッドなしで)、元のスレッドが結果を必要とするまで他のことを続けることをより重視しています。


ただし、promiseまたはfutureのいずれかが完了するまで、任意の計算ブロックを設定できます。つまり:(@ a + @b)は、将来と約束の両方で同じように機能します
appshare.co 2011年

2
約束はそれが私に見えるより多くの柔軟性を可能にします。私は約束をします。その約束を別のスレッドに渡します。その後、I / Oの待機、インターネットからのデータのダウンロード、ユーザー入力の待機など、多くの複雑な計算を実行できます。すべてが完了すると、結果の値で約束を果たします。未来は1つのS式をカバーします。非常に複雑なS式になる可能性がありますが、少し難しいでしょう。さらに、futureはスレッド(またはプール)で自動的に機能します。約束で同じことをすることは、さらに多くの仕事を意味するでしょう。
ちょうど私の正しい意見2011年

FWIW単一のs式は任意のコードパスの呼び出しになる可能性があるため、式に詰め込めるコードの量は必ずしも重要ではありません。したがって、約束が「より柔軟」であると言う代わりに、その目的は単に異なると言えます。そうでなければ、なぜ両方を持っているのですか?
Geoff 2012

2
念のため、future通話の本文にはN個のsexprを含めることができます。
vemv 2012

この説明は、Clojure Doc
PiyushKatariya18年

25

FutureとPromiseはどちらも、非同期計算の結果をプロデューサーからコンシューマーに伝達するメカニズムです。Future

場合、計算はFutureの作成時に定義され、非同期実行は「ASAP」で開始されます。また、非同期計算を生成する方法も「知っています」。 以下の場合にはプロミス演算、その開始時間と【可能】非同期呼び出しは、送達機構から分離されています。ときの計算結果が利用可能であるプロデューサーは、呼び出す必要があります。また、そのプロデューサーコントロールを意味し、明示する場合、結果が利用可能になります。

deliver

以下のために約束のClojureは同じオブジェクト(の結果使用して、設計ミスをするpromise(両方生成するコール)deliver)及び(消費deref)の結果を計算。これらは2つの非常に異なる機能であり、そのように扱う必要があります。


@oskarkvプロミスを作成し、それを3人のクライアントに渡したとします。クライアントの1つが偽の結果でそれを解決し、他の2つのクライアントに通知することを妨げるものは何もありません。さらに、この約束を解決することはできなくなります。対照的に、promise + resolverのペアがあり、クライアントにpromiseを与え、resolverを自分で保持している場合、このシナリオは不可能になります。詳細については、推奨される検索用語は「機能ベースのアクセス制御」と「機能ベースのセキュリティ」です。
dimagog 2012

1
セキュリティをそのような単純な参照型(そのimplをチェックしてください)にそのまま結合promiseするのが便利かどうかはわかりません。「邪悪な」消費者はまれです。約束の上に独自の抽象化を構築することを妨げるものは何もありません。
vemv 2012

8
それはセキュリティに関するものではなく、機能ベースのプログラミングがセキュリティに関連して説明されることがよくあることです。ここでは、コードの正確性がすべてです。よく使われる用語は「構築によって正しい」であり、質問は「間違ったプログラムを構築できますか」です。故意ではなく、偶然です。単一のPromiseオブジェクトでは可能ですが、2つの別々のオブジェクトでは不可能です。
dimagog 2012

それがあなたが望むものであるならば、しかし、あなたが配達できない約束を返すことを(defn undeliverable-promise [] (let [p (promise)] (reify clojure.lang.IDeref (deref [_] (deref p)) clojure.lang.IBlockingDeref (deref [_ ms val] (deref p ms val)) clojure.lang.IPending (isRealized [_] (.isRealized p)) clojure.lang.IFn (invoke [_ _] nil))))
妨げる

計算メカニズムがどのように分離されているかの違いを指摘することで、この投稿は本当に簡潔な説明になりました。ありがとう!
synthomat

3

すでに優れた答えがあるので、「使い方」の要約を追加するだけです。

両方とも

promiseまたはfutureを作成すると、参照がすぐに返されます。この参照は、計算結果が他のスレッドによって提供されるまで、@ / derefでブロックされます。

未来

フューチャーを作成するときは、実行する同期ジョブを提供します。専用の無制限プールからのスレッドで実行されます。

約束する

promiseを作成するときは、引数を指定しません。参照はdeliver、結果になる他の「ユーザー」スレッドに渡される必要があります。


1

Clojureのでは、promisefuture、とdelay約束のようなオブジェクトです。これらはすべて、クライアントがderef(または@)を使用して待機できる計算を表します。クライアントは結果を再利用するため、計算が数回実行されることはありません。

これらは、計算の実行方法が異なります。

  • future別のワーカースレッドで計算を開始します。deref結果の準備ができるまでブロックします。

  • delay最初のクライアントが、、derefまたはを使用すると、計算が遅延して実行されますforce

  • promise結果はを使用してカスタムの方法で配信されるため、最も柔軟性がありますdeliver。どちらfutureでもない場合、またはdelayユースケースと一致しない場合に使用します。


-4

まず、aPromiseFutureです。aPromiseとaの違いを知りたいと思いますFutureTask

AFutureは、現在は不明ですが、将来は既知になる値を表します。

AFutureTaskは、将来(おそらくいくつかのスレッドプールで)発生する計算の結果を表します。結果にアクセスしようとすると、計算がまだ行われていない場合はブロックされます。それ以外の場合、結果はすぐに返されます。計算は事前に指定されているため、結果の計算に関与する他の当事者は存在しません。

APromiseは、将来、約束者から約束者に配信される結果を表します。この場合、あなたは約束者であり、約束者はあなたにPromiseオブジェクトを与えた人です。と同様に、FutureTaskが実行される前に結果にアクセスしようとするとPromise、約束者がが実行されるまで結果はブロックされPromiseます。いったんPromise満たされ、いつでも、すぐに同じ値を取得します。とは異なり、FutureTaskここには別のパーティが含まれていPromiseます。その別の当事者は、計算を実行し、を実行する責任がありPromiseます。

その意味で、aFutureTaskPromiseあなたが自分で作ったものです。


約束は未来だと確信していますか?私はそれがインターフェースを実装していることを見つけることができません。github.com/richhickey/clojure/blob/…–
Mikael Sundberg

申し訳ありませんが、入力を間違えました。私の質問が変更されました
Mikael Sundberg 2011年

私の答えは一般的な意味であり、Clojure固有のものではありません。
Abhinav Sarkar 2011年

9
JavaコードでClojureに関する質問に答えるのは、少し気まぐれなようです。
ちょうど私の正しい意見2011年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.