Scala Cookbook( http://shop.oreilly.com/product/0636920026914.do )を読んでいます。
理解に関係する将来の使用に関連する例があります。
これまでの理解に対する私の理解は、コレクションで使用すると、同じタイプの別のコレクションが生成されることです。たとえば、各futureX
のタイプがFuture[Int]
、次のタイプもFuture[Int]
:
for {
r1 <- future1
r2 <- future2
r3 <- future3
} yield (r1+r2+r3)
誰かが私に<-
このコードでは?ジェネレーターである場合、ループによって各要素をフェッチします。
まず理解のために。 SOで何度も答えられました。これは、いくつかのモナド演算map
、flatMap
、withFilter
。]に対する抽象化であると答えました。 _<-
_を使用すると、scalacはこの行をモナドflatMap
に脱糖します。
_r <- monad
_ into monad.flatMap(r => ... )
それは命令型の計算のように見えます(モナドのすべて)、計算結果をr
にバインドします。そして、yield
部分はmap
呼び出しに脱糖されます。結果のタイプは、monad
のタイプに依存します。
Future
トレイトにはflatMap
およびmap
関数があるため、理解に使用できます。あなたの例では、次のコードに脱糖できます:
_future1.flatMap(r1 => future2.flatMap(r2 => future3.map(r3 => r1 + r2 + r3) ) )
_
_future2
_の実行が_r1
_に依存する場合、シーケンシャル実行をエスケープできないことは言うまでもありませんが、将来の計算が独立している場合、2つの選択肢があります。順次実行、またはallowを並列実行に強制できます。実行コンテキストがこれを処理するので、enforce後者はできません。
_val res = for {
r1 <- computationReturningFuture1(...)
r2 <- computationReturningFuture2(...)
r3 <- computationReturningFuture3(...)
} yield (r1+r2+r3)
_
常に連続して実行されます。脱糖によって簡単に説明できます。その後、後続のcomputationReturningFutureX
呼び出しはflatMaps内でのみ呼び出されます。
_computationReturningFuture1(...).flatMap(r1 =>
computationReturningFuture2(...).flatMap(r2 =>
computationReturningFuture3(...).map(r3 => r1 + r2 + r3) ) )
_
ただし、これは並行して実行でき、理解のために結果が集約されます。
_val future1 = computationReturningFuture1(...)
val future2 = computationReturningFuture2(...)
val future3 = computationReturningFuture3(...)
val res = for {
r1 <- future1
r2 <- future2
r3 <- future3
} yield (r1+r2+r3)
_
これらの既存の回答を詳しく説明するには、for
内包表記がどのように機能するかを示す簡単な結果を示します。
少し長く機能しますが、見てみる価値はあります。
整数の範囲を与える関数
scala> def createIntegers = Future{
println("INT "+ Thread.currentThread().getName+" Begin.")
val returnValue = List.range(1, 256)
println("INT "+ Thread.currentThread().getName+" End.")
returnValue
}
createIntegers: createIntegers: scala.concurrent.Future[List[Int]]
一連の文字を提供する関数
scala> def createAsciiChars = Future{
println("CHAR "+ Thread.currentThread().getName+" Begin.")
val returnValue = new ListBuffer[Char]
for (i <- 1 to 256){
returnValue += i.toChar
}
println("CHAR "+ Thread.currentThread().getName+" End.")
returnValue
}
createAsciiChars: scala.concurrent.Future[scala.collection.mutable.ListBuffer[Char]]
これらの関数呼び出しを使用してwithinを理解します。
scala> val result = for{
i <- createIntegers
s <- createAsciiChars
} yield i.Zip(s)
Await.result(result, Duration.Inf)
result: scala.concurrent.Future[List[(Int, Char)]] = Future(<not completed>)
以下の行では、すべての関数呼び出しが同期的であることがわかります。つまり、createAsciiChars
関数呼び出しは、createIntegers
が実行を完了するまで実行されないです。
scala> INT scala-execution-context-global-27 Begin.
INT scala-execution-context-global-27 End.
CHAR scala-execution-context-global-28 Begin.
CHAR scala-execution-context-global-28 End.
これらの関数createAsciiChars
、createIntegers
内包の外側のfor
呼び出しは、非同期実行になります。