以下の例では、例外_Java.util.NoSuchElementException: Future.filter predicate is not satisfied
_が発生します
チェックFuture( Test2 )
が失敗したときに結果if( i == 2 )
が欲しい。フィルターを処理する方法/ if内で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
_
_for-comprehension
_では、_i == 2
_でフィルタリングしています。 _f1
_の値は2ではないため、Success
ではなくFailure
が生成されます。エラーメッセージが示すように、フィルターの述語は満たされていません。ただし、_f2.recover
_は新しいFuture
を返します。 _f2
_の値は操作されません。 Failure
はまだ保存されています。そのため、_f2.value
_を呼び出すとエラーメッセージが表示されます。
ここ に示すように、_for-comprehension
_でelse
を使用することが、私が考えられる唯一の代替案です。
_val f2 = for ( i <- f1) yield {
if (i == 2) "Test1"
else "Test2"
}
f2.value
_
これは、_f3.value
_と同じようにSome(Success(Test2))
を返します。
私の意見では、これはより慣用的な解決策です。この述語関数は、_Future[Unit]
_または例外を含む失敗したfutureを作成します。あなたの例では、これはSuccess("Test1")
または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"
_
もちろん、自分で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
@pkinskyのアイデアが気に入り、少し改善しました。次のようなException
オブジェクトを作成するコードをドロップしました:
val f2 = for {
i <- f1
_ <- shouldTrue( i == 2 )
j <- f3 // f3 will only run if the predicate is true
} yield "Test1"
shouldTrue
関数は、lihaoyiの sourcecode ライブラリを使用して実装されます。
def shouldTrue(condition: sourcecode.Text[Boolean])(implicit enclosing: sourcecode.Enclosing, file: sourcecode.File, line: sourcecode.Line): Future[Unit] =
if (condition.value) Future.successful( () ) else Future.failed(new Exception(s"${condition.source} returns false\n\tat ${file.value}:${line.value}"))
次に、より意味のある例外メッセージを自動的に生成します。
Java.lang.Exception: i == 2 returns false
at \path\to\example.scala:17