@@ -139,43 +139,19 @@ Future の実装の多くは、Future の結果を知りたくなったクライ
139139 }
140140
141141` onComplete ` メソッドは、Future 計算の失敗と成功の両方の結果を扱えるため、汎用性が高い。
142- 成功した結果のみ扱う場合は、(部分関数を受け取る) ` onSuccess ` コールバックを使う:
142+ 成功した結果のみ扱う場合は、` foreach ` コールバックを使う:
143143
144144 val f: Future[List[String]] = Future {
145145 session.getRecentPosts
146146 }
147147
148- f onSuccess {
149- case posts => for (post <- posts) println(post)
148+ f foreach { posts =>
149+ for (post <- posts) println(post)
150150 }
151151
152- 失敗した結果のみ扱う場合は、` onFailure ` コールバックを使う:
153-
154- val f: Future[List[String]] = Future {
155- session.getRecentPosts
156- }
157-
158- f onFailure {
159- case t => println("エラーが発生した: " + t.getMessage)
160- }
161-
162- f onSuccess {
163- case posts => for (post <- posts) println(post)
164- }
165-
166- ` onFalure ` コールバックは Future が失敗した場合、つまりそれが例外を保持する場合のみ実行される。
167-
168- 部分関数は ` isDefinedAt ` メソッドを持つため、` onFailure ` メソッドはコールバックが特定の ` Throwable ` に対して定義されている場合のみ発火される。
169- 以下の例では、登録された ` onFailure ` コールバックは発火されない:
170-
171- val f = Future {
172- 2 / 0
173- }
174-
175- f onFailure {
176- case npe: NullPointerException =>
177- println("これが表示されているとしたらビックリ。")
178- }
152+ ` Future ` は、失敗した結果のみを処理する方法を提供していて、
153+ ` Failure[Throwable] ` を ` Success[Throwable] ` へと変換する ` failed ` 投射を用いることができる。
154+ 詳細は以下の[ 投射] ( #projections ) を参照。
179155
180156キーワードの初出の位置を検索する例に戻ると、キーワードの位置を画面に表示したいかもしれない:
181157
@@ -184,15 +160,12 @@ Future の実装の多くは、Future の結果を知りたくなったクライ
184160 source.toSeq.indexOfSlice("myKeyword")
185161 }
186162
187- firstOccurence onSuccess {
188- case idx => println("キーワードの初出位置: " + idx)
189- }
190-
191- firstOccurence onFailure {
192- case t => println("ファイルの処理に失敗した: " + t.getMessage)
163+ firstOccurence oncomplete {
164+ case Success(idx) => println("キーワードの初出位置: " + idx)
165+ case Failure(t) => println("処理失敗:" + t.getMessage)
193166 }
194167
195- ` onComplete ` 、` onSuccess ` 、 および ` onFailure ` メソッドは全て ` Unit ` 型を返すため、これらの呼び出しを連鎖させることができない。
168+ ` onComplete ` 、および ` foreach ` メソッドは全て ` Unit ` 型を返すため、これらの呼び出しを連鎖させることができない。
196169これは意図的な設計で、連鎖された呼び出しが登録されたコールバックの実行の順序を暗示しないようにしている
197170(同じ Future に登録されたコールバックは順不同に発火される)。
198171
@@ -212,12 +185,12 @@ Future 内の値が利用可能となることを必要とするため、Future
212185 "na" * 16 + "BATMAN!!!"
213186 }
214187
215- text onSuccess {
216- case txt => totalA += txt.count(_ == 'a')
188+ text.foreach { txt =>
189+ totalA += txt.count(_ == 'a')
217190 }
218191
219- text onSuccess {
220- case txt => totalA += txt.count(_ == 'A')
192+ text.foreach { txt =>
193+ totalA += txt.count(_ == 'A')
221194 }
222195
2231962つのコールバックが順次に実行された場合は、変数 ` totalA ` は期待される値 ` 18 ` を持つ。
@@ -232,7 +205,7 @@ Future 内の値が利用可能となることを必要とするため、Future
232205<ol >
233206<li >Future に <code >onComplete</code > コールバックを登録することで、対応するクロージャが Future が完了した後に eventually に実行されることが保証される。</li >
234207
235- <li ><code >onSuccess</ code > や < code >onFailure </code > コールバックを登録することは <code >onComplete</code > と同じ意味論を持つ。ただし、クロージャがそれぞれ成功したか失敗した場合のみに呼ばれるという違いがある。</li >
208+ <li ><code >foreach </code > コールバックを登録することは <code >onComplete</code > と同じ意味論を持つ。ただし、クロージャがそれぞれ成功したか失敗した場合のみに呼ばれるという違いがある。</li >
236209
237210<li >既に完了した Future にコールバックを登録することは (1 により) コールバックが eventually に実行されることとなる。</li >
238211
@@ -257,33 +230,32 @@ Future 内の値が利用可能となることを必要とするため、Future
257230 connection.getCurrentValue(USD)
258231 }
259232
260- rateQuote onSuccess { case quote =>
233+ for (quote <- rateQuote) {
261234 val purchase = Future {
262235 if (isProfitable(quote)) connection.buy(amount, quote)
263236 else throw new Exception("有益ではない")
264237 }
265238
266- purchase onSuccess {
267- case _ => println(amount + " USD を購入した")
268- }
239+ for (amount <- purchase)
240+ println(amount + " USD を購入した")
269241 }
270242
271243まずは現在の為替相場を取得する ` rateQuote ` という ` Future ` を作る。
272244この値がサーバから取得できて Future が成功した場合は、計算は
273- ` onSuccess ` コールバックに進み、ここで買うかどうかの決断をすることができる。
245+ ` foreach ` コールバックに進み、ここで買うかどうかの決断をすることができる。
274246ここでもう 1つの Future である ` purchase ` を作って、有利な場合のみ買う決定をしてリクエストを送信する。
275247最後に、` purchase ` が完了すると、通知メッセージを標準出力に表示する。
276248
277249これは動作するが、2つの理由により不便だ。
278- 第一に、` onSuccess ` を使わなくてはいけなくて、2つ目の Future である
250+ 第一に、` foreach ` を使わなくてはいけなくて、2つ目の Future である
279251` purchase ` をその中に入れ子にする必要があることだ。
280252例えば ` purchase ` が完了した後に別の貨幣を売却したいとする。
281- それはまた ` onSuccess ` の中でこのパターンを繰り返すことになり、インデントしすぎで理解しづらく肥大化したコードとなる。
253+ それはまた ` foreach ` の中でこのパターンを繰り返すことになり、インデントしすぎで理解しづらく肥大化したコードとなる。
282254
283- 第二に、` purchase ` は他のコードのスコープ外にあり、` onSuccess `
255+ 第二に、` purchase ` は他のコードのスコープ外にあり、` foreach `
284256コールバック内においてのみ操作することができる。
285257そのため、アプリケーションの他の部分は ` purchase ` を見ることができず、他の貨幣を売るために別の
286- ` onSuccess ` コールバックを登録することもできない。
258+ ` foreach ` コールバックを登録することもできない。
287259
288260これらの 2つの理由から Future はより自然な合成を行うコンビネータを提供する。
289261基本的なコンビネータの 1つが ` map ` で、これは与えられた Future
@@ -301,11 +273,11 @@ Future の投射はコレクションの投射と同様に考えることがで
301273 else throw new Exception("有益ではない")
302274 }
303275
304- purchase onSuccess {
305- case _ => println(amount + " USD を購入した")
276+ purchase.foreach { amount =>
277+ println(amount + " USD を購入した")
306278 }
307279
308- ` rateQuote ` に対して ` map ` を使うことで ` onSuccess ` コールバックを一切使わないようになった。
280+ ` rateQuote ` に対して ` map ` を使うことで ` foreach ` コールバックを一切使わないようになった。
309281それと、より重要なのが入れ子が無くなったことだ。
310282ここで他の貨幣を売却したいと思えば、` purchase ` に再び ` map ` するだけでいい。
311283
@@ -321,7 +293,7 @@ Future の投射はコレクションの投射と同様に考えることがで
321293この例外を伝搬させる意味論は他のコンビネータにおいても同様だ。
322294
323295Future の設計指針の 1つは for 内包表記から利用できるようにすることだった。
324- このため、Future は ` flatMap ` 、 ` filter ` そして ` foreach ` コンビネータを持つ。
296+ このため、Future は ` flatMap ` そして ` withFilter ` コンビネータを持つ。
325297` flatMap ` メソッドは値を新しい Future ` g ` に投射する関数を受け取り、` g `
326298が完了したときに完了する新たな Future を返す。
327299
@@ -338,8 +310,8 @@ Future の設計指針の 1つは for 内包表記から利用できるように
338310 if isProfitable(usd, chf)
339311 } yield connection.buy(amount, chf)
340312
341- purchase onSuccess {
342- case _ => println(amount + " CHF を購入した")
313+ purchase foreach { _ =>
314+ println(amount + " CHF を購入した")
343315 }
344316
345317この ` purchase ` は ` usdQuote ` と ` chfQuote ` が完了した場合のみ完了する。
@@ -370,10 +342,6 @@ Future に関しては、`filter` の呼び出しは `withFilter` の呼び出
370342
371343` collect ` と ` filter ` コンビネータの関係はコレクション API におけるこれらのメソッドの関係に似ている。
372344
373- ` foreach ` コンビネータで注意しなければいけないのは値が利用可能となった場合に走査するのにブロックしないということだ。
374- かわりに、` foreach ` のための関数は Future が成功した場合のみ非同期に実行される。
375- そのため、` foreach ` は ` onSuccess ` コールバックと全く同じ意味を持つ。
376-
377345` Future ` トレイトは概念的に (計算結果と例外という) 2つの型の値を保持することができるため、例外処理のためのコンビネータが必要となる。
378346
379347` rateQuote ` に基いて何らかの額を買うとする。
@@ -418,7 +386,7 @@ Future は同じ `Throwable` とともに失敗する。
418386
419387 val anyQuote = usdQuote fallbackTo chfQuote
420388
421- anyQuote onSuccess { println(_) }
389+ anyQuote foreach { println(_) }
422390
423391` andThen ` コンビネータは副作用の目的のためだけに用いられる。
424392これは、成功したか失敗したかに関わらず現在の Future と全く同一の結果を返す新たな Future を作成する。
@@ -454,12 +422,18 @@ Future は同じ `Throwable` とともに失敗する。
454422 }
455423 for (exc <- f.failed) println(exc)
456424
425+ 上の例での for 内包表記は以下のように書き換えることができる:
426+
427+ f.failed.foreach( exc => println(exc))
428+
429+ ` f ` が失敗したため、クロージャは新規に成功値を持つ ` Future[Throwable] ` の
430+ ` foreach ` コールバックに登録される。
457431以下の例は画面に何も表示しない:
458432
459- val f = Future {
433+ val g = Future {
460434 4 / 2
461435 }
462- for (exc <- f .failed) println(exc)
436+ for (exc <- g .failed) println(exc)
463437
464438<!--
465439There is another projection called `timedout` which is specific to the
@@ -536,8 +510,7 @@ Future が失敗した場合は、呼び出し元には Future が失敗した
536510
537511非同期の計算が処理されない例外を投げた場合、その計算が行われた Future は失敗する。
538512失敗した Future は計算値のかわりに ` Throwable ` のインスタンスを格納する。
539- ` Future ` は、` Throwable ` に適用することができる ` PartialFunction ` を受け取る
540- ` onFailure ` コールバックメソッドを提供する。
513+ また、` Future ` はこの ` Throwable ` インスタンスを別の ` Future ` の計算値として扱う ` failed ` 投射メソッドを提供する。
541514以下の特別な例外に対しては異なる処理が行われる:
542515
5435161 . ` scala.runtime.NonLocalReturnControl[_] ` 。この例外は戻り値に関連する値を保持する。
@@ -576,14 +549,14 @@ Promise の `p` は `p.future` によって返される Future を完了させ
576549
577550 val producer = Future {
578551 val r = produceSomething()
579- p success r
552+ p. success(r)
580553 continueDoingSomethingUnrelated()
581554 }
582555
583556 val consumer = Future {
584557 startDoingSomething()
585- f onSuccess {
586- case r => doSomethingWithResult()
558+ f.foreach { r =>
559+ doSomethingWithResult()
587560 }
588561 }
589562
@@ -644,8 +617,8 @@ HTTP レスポンスにのみ興味がある場合で、これは最初に Promi
644617
645618 p completeWith f
646619
647- p.future onSuccess {
648- case x => println(x)
620+ p.future.foreach { x =>
621+ println(x)
649622 }
650623
651624Promise を例外とともに失敗させる場合は、` Throwable ` の 3つのサブタイプが特殊扱いされる。
@@ -664,12 +637,12 @@ Promise、Future の `onComplete` メソッド、そして `future`
664637 def first[T](f: Future[T], g: Future[T]): Future[T] = {
665638 val p = Promise[T]()
666639
667- f onSuccess {
668- case x => p.tryComplete(x)
640+ f.foreach { x =>
641+ p.tryComplete(x)
669642 }
670643
671- g onSuccess {
672- case x => p.tryComplete(x)
644+ g.foreach { x =>
645+ p.tryComplete(x)
673646 }
674647
675648 p.future
0 commit comments