23

以下の例では、例外が発生しますjava.util.NoSuchElementException: Future.filter predicate is not satisfied

Future( Test2 )チェックif( i == 2 )が失敗したときに結果を取得したい。フューチャの構成を扱う for 内包内で filter/if を処理するにはどうすればよいですか?

以下は、Scala REPL で動作する簡単な例です。

コード:

import scala.concurrent.Future
import scala.util.{ Try, Success, Failure }
import scala.concurrent.ExecutionContext.Implicits.global

val f1 = Future( 1 )
val f2 = for {
  i <- f1
  if( i == 2 )
} yield "Test1"
f2.recover{ case _ => "Test2" }
f2.value
4

4 に答える 4

31

私の意見では、これはより慣用的な解決策です。この述語関数はFuture[Unit]、例外を含むまたは失敗した未来を作成します。あなたの例では、これは aSuccess("Test1")または a になりFailure(Exception("Test2"))ます。これは「Test1」や「Test2」とは少し異なりますが、この構文の方が便利だと思います。

def predicate(condition: Boolean)(fail: Exception): Future[Unit] = 
    if (condition) Future( () ) else Future.failed(fail)

次のように使用します。

val f2 = for {
  i <- f1
  _ <- predicate( i == 2 )(new Exception("Test2"))
  j <- f3  // f3 will only run if the predicate is true
} yield "Test1"
于 2014-03-09T22:29:04.723 に答える
13

で、for-comprehensionでフィルタリングしていi == 2ます。の値はf12 ではないため、 aSuccessではなく が生成されFailureます。エラーメッセージが示すように、フィルターの述語は満たされていません。ただし、f2.recover新しい を返しますFuture。の値f2は操作されません。それはまだ保存されていFailureます。これが、 を呼び出したときにエラー メッセージが表示される理由ですf2.value

私が考えることができる唯一の代替手段は、ここに示されているようelseに in yourを使用することです。for-comprehension

val f2 = for ( i <- f1) yield {
  if (i == 2) "Test1"
  else "Test2"
}
f2.value

これはあなたのように戻りSome(Success(Test2))ますf3.value

于 2013-07-26T07:31:07.743 に答える
9

もちろん、私は自分で1つの解決策を見つけました。おそらく、より優れた、より慣用的な解決策があるでしょうか?

import scala.concurrent.Future
import scala.util.{ Try, Success, Failure }
import scala.concurrent.ExecutionContext.Implicits.global

val f1 = Future( 1 )
val f2 = for {
  i <- f1
  if( i == 2 )
} yield "Test1"
val f3 = f2.recover{ case _ => "Test2"  }
// OR val f3 = f2.fallbackTo( Future( "Test2" ) )
f3.value
于 2013-07-25T22:15:17.100 に答える