future, promise, delay とは、プログラミング言語における並列処理のデザインパターン。何らかの処理を別のスレッドで処理させる際、その処理結果の取得を必要になるところまで後回しにする手法。処理をパイプライン化させる。1977年に考案され、現在ではほとんどのプログラミング言語で利用可能。

概要 カール・ヒューイットは、2つの点で future の方が promise よりも適した用語であるとしている。第一に promise(約束)は必ずしも将来の時点のことを意味しないため、future(未来)よりも曖昧である。第二に promise は単なる言語表現だが、future は現物(actuals)に対する先物(futures)という意味もある(つまり、実際の物に対する代用品)。

future という構文が最初に紹介されたのは1977年、とカール・ヒューイットの論文でのことであった。一方 promise という用語は、1976年にとデビッド・ワイズが提案し、最終的にピーター・ヒバードが呼んだものである。future (promise) の使用により、分散システムにおける遅延を劇的に減少させることができる。例えばアクターモデルのようにメッセージのパイプライン化が可能であり、これをやでは promise pipelining と呼ぶ。

パイプライン化 一般的なRPCで次のような式を考える。 t3 := (x.a()).c(y.b())

これは、次のように展開できる。 t1 := x.a(); t2 := y.b(); t3 := t1.c(t2)

これを解釈すると、t1 および t2 の値が定まらないと t3 の値は計算できない。future を使うとこの式が次のように表される。 t3 := future (future x.a()).c(future y.b())

これを展開すると次のようになる。 t1 := future x.a(); t2 := future y.b(); t3 := future t1.c(t2)

このようにすると t3 は即座に計算される。ただし、t3 から情報を得ようとすると待たされる。

実装 future構文は MultiLisp や Act1 といったプログラミング言語で実装された。並行論理プログラミング言語における論理変数もよく似ている。これは当初 Prolog with Freeze や IC Prolog で使われ、Relational Language、Concurrent Prolog、PARLOG、GHC、KL1、Strand、Vulcan、Janus、Mozart/Oz、Flow Java、Alice といった言語で真の並行性プリミティブとなった。Concurrent ML のような単一代入規則型データフロー言語の I-var は並行論理変数とよく似ている。

future による遅延最小化のようなパイプライン化技法はまずアクターモデルで生み出され、1988年にバーバラ・リスコフが再発明し、1989年ごろにはザナドゥ計画でも再発明されている。

future, promise, 並行論理変数, データフロー変数, I-var をサポートする言語: ABCL/f Act1

(first-class resolvers と read-only promises を含む) C++ (C++11以降のstd::futureとstd::promise、C++20以降のco_await)

C# (C# 5.0以降のasync/await構文) Concurrent Prolog Dart (Future/Completerクラス、async/awaitキーワード)

Glasgow Haskell (I-vars and M-vars only) GHC (I-vars and M-vars only) Io Java: Java 1.5以降の JavaScript (ECMAScript): ES2015 (ES6) 以降のPromise、ES2017以降のasync/await構文 KL1(その実装としてKLICがある) LISP系言語 Clojure

Scheme Lucid (データフローのみ)

Oz version 3(その実装としてMozart Programming Systemがある) Python 3.2, PEP 3148 で提案 R (promises for lazy evaluation - still single threaded) Racket Scala Visual Basic .NET (VB.NET 11以降のAsync/Await構文) C#やVB.NETなどの.NET言語全般: .NET 4以降のタスク並列ライブラリ (Parallel Extensions) Nim

加えて、promise pipelining をサポートする言語: Joule言語 E言語

非標準ライブラリによる実装: Common Lisp: Eager Future2, PCall C++: Boost C++ライブラリにおけるboost::futureBoost.Futureとboost::promiseBoost.Promise Dlib C++ Library マイクロソフトによる同時実行ランタイム (ConCRT) のにおけるconcurrency::taskTask Parallelism (Concurrency Runtime) | Microsoft Docs Groovy: GPars JavaScript: Cujo.js - CommonJS Promises/A に基づく promise を when.js が提供 Dojo Toolkit - promises と Twisted style Deferred を提供 jQuery - CommonJS Promises/A に基づく物を Deferred Object で提供 node-promise Q RSVP.js Java: JQuery.Deferred に似た振る舞いを JDeferred の Deferred/Promise API が提供 Objective-C: MAFuture (reference), PromiseKit, Promises OCaml: Lazy モジュールが lazy explicit future を実装 Perl: Future, Reflex PHP: React/Promise Python: pythonfutures, Twisted's Deferreds Ruby: Promise gem Swift: FutureKit, BrightFutures, PromiseKit, Promises

参考文献 Henry Baker and Carl Hewitt The Incremental Garbage Collection of Processes Proceeding of the Symposium on Artificial Intelligence Programming Languages. SIGPLAN Notices 12, August 1977. Henry Lieberman. Thinking About Lots of Things at Once without Getting Confused: Parallelism in Act 1 MIT AI memo 626. May 1981. Henry Lieberman. A Preview of Act 1 MIT AI memo 625. June 1981.

脚注

関連項目 評価戦略#未来呼び ファイバー (コンピュータ) コルーチン Async/await

外部リンク Portland Pattern Repository Future Value Promise Pipelining