@@ -139,43 +139,18 @@ Future の実装の多くは、Future の結果を知りたくなったクライ
139
139
}
140
140
141
141
` onComplete ` メソッドは、Future 計算の失敗と成功の両方の結果を扱えるため、汎用性が高い。
142
- 成功した結果のみ扱う場合は、(部分関数を受け取る) ` onSuccess ` コールバックを使う:
142
+ 成功した結果のみ扱う場合は、` foreach ` コールバックを使う:
143
143
144
144
val f: Future[List[String]] = Future {
145
145
session.getRecentPosts
146
146
}
147
147
148
- f onSuccess {
149
- case posts => for (post <- posts) println(post)
148
+ f foreach { posts =>
149
+ for (post <- posts) println(post)
150
150
}
151
151
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
+ 失敗した結果のみ扱う場合は、 ` Failure[Throwable] ` から` Success[Throwable] ` に返送する
153
+ ` failed ` 投射を使う。詳細は[ 投射] ( #projections ) を参照。
179
154
180
155
キーワードの初出の位置を検索する例に戻ると、キーワードの位置を画面に表示したいかもしれない:
181
156
@@ -184,15 +159,12 @@ Future の実装の多くは、Future の結果を知りたくなったクライ
184
159
source.toSeq.indexOfSlice("myKeyword")
185
160
}
186
161
187
- firstOccurence onSuccess {
188
- case idx => println("キーワードの初出位置: " + idx)
189
- }
190
-
191
- firstOccurence onFailure {
192
- case t => println("ファイルの処理に失敗した: " + t.getMessage)
162
+ firstOccurence oncomplete {
163
+ case Success(idx) => println("キーワードの初出位置: " + idx)
164
+ case Failure(t) => println("処理失敗:" + t.getMessage)
193
165
}
194
166
195
- ` onComplete ` 、` onSuccess ` 、 および ` onFailure ` メソッドは全て ` Unit ` 型を返すため、これらの呼び出しを連鎖させることができない。
167
+ ` onComplete ` 、および ` foreach ` メソッドは全て ` Unit ` 型を返すため、これらの呼び出しを連鎖させることができない。
196
168
これは意図的な設計で、連鎖された呼び出しが登録されたコールバックの実行の順序を暗示しないようにしている
197
169
(同じ Future に登録されたコールバックは順不同に発火される)。
198
170
@@ -212,12 +184,12 @@ Future 内の値が利用可能となることを必要とするため、Future
212
184
"na" * 16 + "BATMAN!!!"
213
185
}
214
186
215
- text onSuccess {
216
- case txt => totalA += txt.count(_ == 'a')
187
+ text.foreach { txt =>
188
+ totalA += txt.count(_ == 'a')
217
189
}
218
190
219
- text onSuccess {
220
- case txt => totalA += txt.count(_ == 'A')
191
+ text.foreach { txt =>
192
+ totalA += txt.count(_ == 'A')
221
193
}
222
194
223
195
2つのコールバックが順次に実行された場合は、変数 ` totalA ` は期待される値 ` 18 ` を持つ。
@@ -232,7 +204,7 @@ Future 内の値が利用可能となることを必要とするため、Future
232
204
<ol >
233
205
<li >Future に <code >onComplete</code > コールバックを登録することで、対応するクロージャが Future が完了した後に eventually に実行されることが保証される。</li >
234
206
235
- <li ><code >onSuccess</ code > や < code >onFailure </code > コールバックを登録することは <code >onComplete</code > と同じ意味論を持つ。ただし、クロージャがそれぞれ成功したか失敗した場合のみに呼ばれるという違いがある。</li >
207
+ <li ><code >foreach </code > コールバックを登録することは <code >onComplete</code > と同じ意味論を持つ。ただし、クロージャがそれぞれ成功したか失敗した場合のみに呼ばれるという違いがある。</li >
236
208
237
209
<li >既に完了した Future にコールバックを登録することは (1 により) コールバックが eventually に実行されることとなる。</li >
238
210
@@ -257,33 +229,32 @@ Future 内の値が利用可能となることを必要とするため、Future
257
229
connection.getCurrentValue(USD)
258
230
}
259
231
260
- rateQuote onSuccess { case quote =>
232
+ for( quote <- rateQuote) {
261
233
val purchase = Future {
262
234
if (isProfitable(quote)) connection.buy(amount, quote)
263
235
else throw new Exception("有益ではない")
264
236
}
265
237
266
- purchase onSuccess {
267
- case _ => println(amount + " USD を購入した")
268
- }
238
+ for (amount <- purchase)
239
+ println(amount + " USD を購入した")
269
240
}
270
241
271
242
まずは現在の為替相場を取得する ` rateQuote ` という ` Future ` を作る。
272
243
この値がサーバから取得できて Future が成功した場合は、計算は
273
- ` onSuccess ` コールバックに進み、ここで買うかどうかの決断をすることができる。
244
+ ` foreach ` コールバックに進み、ここで買うかどうかの決断をすることができる。
274
245
ここでもう 1つの Future である ` purchase ` を作って、有利な場合のみ買う決定をしてリクエストを送信する。
275
246
最後に、` purchase ` が完了すると、通知メッセージを標準出力に表示する。
276
247
277
248
これは動作するが、2つの理由により不便だ。
278
- 第一に、` onSuccess ` を使わなくてはいけなくて、2つ目の Future である
249
+ 第一に、` foreach ` を使わなくてはいけなくて、2つ目の Future である
279
250
` purchase ` をその中に入れ子にする必要があることだ。
280
251
例えば ` purchase ` が完了した後に別の貨幣を売却したいとする。
281
- それはまた ` onSuccess ` の中でこのパターンを繰り返すことになり、インデントしすぎで理解しづらく肥大化したコードとなる。
252
+ それはまた ` foreach ` の中でこのパターンを繰り返すことになり、インデントしすぎで理解しづらく肥大化したコードとなる。
282
253
283
- 第二に、` purchase ` は他のコードのスコープ外にあり、` onSuccess `
254
+ 第二に、` purchase ` は他のコードのスコープ外にあり、` foreach `
284
255
コールバック内においてのみ操作することができる。
285
256
そのため、アプリケーションの他の部分は ` purchase ` を見ることができず、他の貨幣を売るために別の
286
- ` onSuccess ` コールバックを登録することもできない。
257
+ ` foreach ` コールバックを登録することもできない。
287
258
288
259
これらの 2つの理由から Future はより自然な合成を行うコンビネータを提供する。
289
260
基本的なコンビネータの 1つが ` map ` で、これは与えられた Future
@@ -301,11 +272,11 @@ Future の投射はコレクションの投射と同様に考えることがで
301
272
else throw new Exception("有益ではない")
302
273
}
303
274
304
- purchase onSuccess {
305
- case _ => println(amount + " USD を購入した")
275
+ purchase.foreach { amount =>
276
+ println(amount + " USD を購入した")
306
277
}
307
278
308
- ` rateQuote ` に対して ` map ` を使うことで ` onSuccess ` コールバックを一切使わないようになった。
279
+ ` rateQuote ` に対して ` map ` を使うことで ` foreach ` コールバックを一切使わないようになった。
309
280
それと、より重要なのが入れ子が無くなったことだ。
310
281
ここで他の貨幣を売却したいと思えば、` purchase ` に再び ` map ` するだけでいい。
311
282
@@ -321,7 +292,7 @@ Future の投射はコレクションの投射と同様に考えることがで
321
292
この例外を伝搬させる意味論は他のコンビネータにおいても同様だ。
322
293
323
294
Future の設計指針の 1つは for 内包表記から利用できるようにすることだった。
324
- このため、Future は ` flatMap ` 、 ` filter ` そして ` foreach ` コンビネータを持つ。
295
+ このため、Future は ` flatMap ` そして ` withFilter ` コンビネータを持つ。
325
296
` flatMap ` メソッドは値を新しい Future ` g ` に投射する関数を受け取り、` g `
326
297
が完了したときに完了する新たな Future を返す。
327
298
@@ -338,8 +309,8 @@ Future の設計指針の 1つは for 内包表記から利用できるように
338
309
if isProfitable(usd, chf)
339
310
} yield connection.buy(amount, chf)
340
311
341
- purchase onSuccess {
342
- case _ => println(amount + " CHF を購入した")
312
+ purchase foreach { _ =>
313
+ println(amount + " CHF を購入した")
343
314
}
344
315
345
316
この ` purchase ` は ` usdQuote ` と ` chfQuote ` が完了した場合のみ完了する。
@@ -370,10 +341,6 @@ Future に関しては、`filter` の呼び出しは `withFilter` の呼び出
370
341
371
342
` collect ` と ` filter ` コンビネータの関係はコレクション API におけるこれらのメソッドの関係に似ている。
372
343
373
- ` foreach ` コンビネータで注意しなければいけないのは値が利用可能となった場合に走査するのにブロックしないということだ。
374
- かわりに、` foreach ` のための関数は Future が成功した場合のみ非同期に実行される。
375
- そのため、` foreach ` は ` onSuccess ` コールバックと全く同じ意味を持つ。
376
-
377
344
` Future ` トレイトは概念的に (計算結果と例外という) 2つの型の値を保持することができるため、例外処理のためのコンビネータが必要となる。
378
345
379
346
` rateQuote ` に基いて何らかの額を買うとする。
@@ -418,7 +385,7 @@ Future は同じ `Throwable` とともに失敗する。
418
385
419
386
val anyQuote = usdQuote fallbackTo chfQuote
420
387
421
- anyQuote onSuccess { println(_) }
388
+ anyQuote foreach { println(_) }
422
389
423
390
` andThen ` コンビネータは副作用の目的のためだけに用いられる。
424
391
これは、成功したか失敗したかに関わらず現在の Future と全く同一の結果を返す新たな Future を作成する。
@@ -454,12 +421,17 @@ Future は同じ `Throwable` とともに失敗する。
454
421
}
455
422
for (exc <- f.failed) println(exc)
456
423
457
- 以下の例は画面に何も表示しない:
424
+ 以上のfor内包表記はこのように訳される
458
425
459
- val f = Future {
426
+ f.failed.foreach( exc => println(exc))
427
+
428
+ ` f ` が失敗したのために、クロージャは新しく成功した` Future[Throwable] ` に
429
+ 登録される。 以下の例は画面に何も表示しない:
430
+
431
+ val g = Future {
460
432
4 / 2
461
433
}
462
- for (exc <- f .failed) println(exc)
434
+ for (exc <- g .failed) println(exc)
463
435
464
436
<!--
465
437
There is another projection called `timedout` which is specific to the
@@ -536,8 +508,7 @@ Future が失敗した場合は、呼び出し元には Future が失敗した
536
508
537
509
非同期の計算が処理されない例外を投げた場合、その計算が行われた Future は失敗する。
538
510
失敗した Future は計算値のかわりに ` Throwable ` のインスタンスを格納する。
539
- ` Future ` は、` Throwable ` に適用することができる ` PartialFunction ` を受け取る
540
- ` onFailure ` コールバックメソッドを提供する。
511
+ ` Future ` の` failed ` 投射メソッドは` Throwable ` の例外を成功したFutureのように処理される。
541
512
以下の特別な例外に対しては異なる処理が行われる:
542
513
543
514
1 . ` scala.runtime.NonLocalReturnControl[_] ` 。この例外は戻り値に関連する値を保持する。
@@ -576,14 +547,14 @@ Promise の `p` は `p.future` によって返される Future を完了させ
576
547
577
548
val producer = Future {
578
549
val r = produceSomething()
579
- p success r
550
+ p. success(r)
580
551
continueDoingSomethingUnrelated()
581
552
}
582
553
583
554
val consumer = Future {
584
555
startDoingSomething()
585
- f onSuccess {
586
- case r => doSomethingWithResult()
556
+ f.foreach { r =>
557
+ doSomethingWithResult()
587
558
}
588
559
}
589
560
@@ -644,8 +615,8 @@ HTTP レスポンスにのみ興味がある場合で、これは最初に Promi
644
615
645
616
p completeWith f
646
617
647
- p.future onSuccess {
648
- case x => println(x)
618
+ p.future.foreach { x =>
619
+ println(x)
649
620
}
650
621
651
622
Promise を例外とともに失敗させる場合は、` Throwable ` の 3つのサブタイプが特殊扱いされる。
@@ -664,12 +635,12 @@ Promise、Future の `onComplete` メソッド、そして `future`
664
635
def first[T](f: Future[T], g: Future[T]): Future[T] = {
665
636
val p = Promise[T]()
666
637
667
- f onSuccess {
668
- case x => p.tryComplete(x)
638
+ f.foreach { x =>
639
+ p.tryComplete(x)
669
640
}
670
641
671
- g onSuccess {
672
- case x => p.tryComplete(x)
642
+ g.foreach { x =>
643
+ p.tryComplete(x)
673
644
}
674
645
675
646
p.future
0 commit comments