2017-06-08 2 views
0

私はListBuffer[Int]を持っていて、それをforeachループで反復し、各ループはこのリストをFuture(現在の要素を削除する)から変更します。リストは空です。例コード:リストを修正するScala先物を含むループ

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.collection.mutable.ListBuffer 

val l = ListBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
l.foreach(n => Future { 
    println(s"Processing $n") 
    Future { 
    l -= n 
    println(s"Removed $n") 
    if (l.isEmpty) println("List is empty!") 
    } 
}) 

これはおそらく非常にひどく終了する予定です。私は同様の構造と同じニーズを持つより複雑なコードを持っていますが、より確実な方法で同じ機能を実現できるように、どのように構造化するのか分かりません。

+0

変更可能にする必要がありますか?将来の未来の理由 – mfirry

+0

@mfirryリストが空のとき(つまり、すべての要素が消費され、アクションが完了したとき)に、何か別のやり方をする必要があります。たとえば、処理中の他の要素が存在する可能性があるため、最後の項目が処理中であることを確認することはできません。 「未来の未来」の部分は、実際のコードの構造を模倣することです。そのような理由があります。ここで少し簡素化しています。 –

+0

しかし、本当にバッファを変更する必要がありますか? – mfirry

答えて

0

あなたの問題を提示する方法は、本当にスケーラが意図している機能的なパラダイムではありません。

あなたが望むように見えるのは、非同期計算のリストを作成し、それぞれの終わりに何かを実行することです。これは、mapflatMapのメソッドを実装するのが簡単な継続をFutureにすると、非常に簡単です。

val fa: Future[Int] = Future { 1 } 
// will apply the function to the result when it becomes available 
val fb: Future[Int] = fa.map(a => a + 1) 
// will start the asynchronous computation using the result when it will become available 
val fc: Future[Int] = fa.flatMap(a => Future { a + 2 }) 

あなたはこのすべてを持っていたら、あなたのFuture完了(成功した)の各とき、あなたは簡単に何かを行うことができます:

ここ
val myFutures: List[Future[Int]] = ??? 
myFutures.map(futInt => futInt.map(int => int + 2)) 

が、私は別の非同期から取得した各値に2を追加しますListの計算。

またFuture.sequenceを使用して完了するために、リスト内のすべてのFutureのを待つことを選択することができます。

val myFutureList: Future[List[Int]] = Future.sequence(myFutures) 

はもう一度、あなたは内部Future秒のときに、各解決されますFutureを取得入力リストが正常に解決されたか、Futureのいずれかが失敗したときに失敗します。この新しいFuturemapまたはflatMapを使用して、すべての計算値を一度に使用することができます。あなたと何かをする値を持つことができるように、私は、本当の機能ではなく、(Unitを返す)手続きを持つ推薦、もちろん

val l = 1 to 10 

val processings: Seq[Future[Unit]] = l.map {n => 
    Future(println(s"processing $n")).map {_ => 
    println(s"finished processing $n") 
    } 
} 

val processingOver: Future[Unit] = 
    Future.sequence(processings).map { (lu: Seq[Unit]) => 
    println(s"Finished processing ${lu.size} elements") 
    } 

:だからここ

は、私はあなたが提案したコードを記述します方法です。私はprintlnを使用してあなたと同じ出力を生成するコードを持っていました(もう何も変わっていないので、少し異なる意味を持つプリントを除いて)。

関連する問題