7

私は Clojure の先物を理解しようとしています。一般的な Clojure の本から例を見てきました。並列計算に先物が使用されている例もあります (これは理にかなっているようです)。

しかし、誰かが O'Reilly の Programming Clojure の本から採用した簡単な例の動作を説明できることを願っています。

(def long-calculation (future (apply + (range 1e8))))

これを逆参照しようとすると、

(time @long-calculation)

正しい結果 (4999999950000000) が返されますが、私のマシンではほぼ瞬時 (0.045 ミリ秒) です。

しかし、実際の関数を呼び出すと、

(time (apply + (range 1e8)))

正しい結果も得られますが、所要時間ははるかに長くなります (〜 5000 ミリ秒)。

未来を逆参照すると、式が評価される新しいスレッドが作成されるというのが私の理解です。その場合、約5000ミリ秒もかかると予想されます。

逆参照された未来が正しい結果をすぐに返すのはなぜですか?

4

1 に答える 1

11

将来の計算は、(別のスレッドで) 将来を作成するとすぐに開始されます。あなたの場合、実行するとすぐに計算が開始されます(def long-calculation ....)

逆参照は、次の 2 つのいずれかを行います。

  • future が完了していない場合は、完了するまでブロックしてから値を返します (これには任意の時間がかかるか、future が終了しない場合は完了しません)。
  • future が完了した場合は、結果を返します。これはほぼ瞬時に行われます (逆参照が非常に高速に返されるのはそのためです)。

以下を比較すると、その効果を確認できます。

;; dereference before future completes
(let [f (future (Thread/sleep 1000))]
  (time @f))
=> "Elapsed time: 999.46176 msecs"

;; dereference after future completes
(let [f (future (Thread/sleep 1000))]
  (Thread/sleep 2000)
  (time @f))
=> "Elapsed time: 0.039598 msecs"
于 2012-05-14T03:25:41.800 に答える