Scala Future带有过滤器,便于理解

Scala Future带有过滤器,便于理解,scala,filter,future,for-comprehension,Scala,Filter,Future,For Comprehension,在下面的示例中,我得到了异常java.util.NoSuchElementException:Future.filter谓词未满足 如果(I==2)检查失败,我希望得到结果Future(Test2)。我如何在一个涉及未来写作的理解框架内处理filter/if 下面是一个在Scala REPL中工作的简化示例 代码: import scala.concurrent.Future import scala.util.{ Try, Success, Failure } import scala.con

在下面的示例中,我得到了异常
java.util.NoSuchElementException:Future.filter谓词未满足

如果(I==2)检查失败,我希望得到结果
Future(Test2)
。我如何在一个涉及未来写作的理解框架内处理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
导入scala.concurrent.Future
导入scala.util.{Try,Success,Failure}
导入scala.concurrent.ExecutionContext.Implicits.global
val f1=未来(1)
val f2=用于{
i“Test2”}
f2.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
导入scala.concurrent.Future
导入scala.util.{Try,Success,Failure}
导入scala.concurrent.ExecutionContext.Implicits.global
val f1=未来(1)
val f2=用于{
i“Test2”}
//或val f3=f2。回退到(未来(“测试2”))
f3.价值

在您的
中,您通过
i==2
进行过滤。因为
f1
的值不是2,所以它不会产生
成功
,而是
失败
。正如错误消息所告诉您的,筛选器的谓词不满足。但是,
f2.recover
返回一个新的
Future
。不操纵
f2
的值。它仍然存储
故障
。这就是调用
f2.value
时收到错误消息的原因。

我能想到的唯一替代方法是在
中使用
else
进行理解,如图所示


val f2=for(i在我看来,这是一个更惯用的解决方案。此谓词函数创建包含异常的
Future[Unit]
或失败的Future。例如,这将导致
成功(“Test1”)
失败(异常(“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"
val f2 = for {
  i <- f1
  _ <- shouldTrue( i == 2 )
  j <- f3  // f3 will only run if the predicate is true
} yield "Test1"
val f2=for{

我我喜欢@pkinsky的想法,并做了一些改进。我删除了创建
异常
对象的代码,如下所示:

val f2 = for {
  i <- f1
  _ <- predicate( i == 2 )(new Exception("Test2"))
  j <- f3  // f3 will only run if the predicate is true
} yield "Test1"
val f2 = for {
  i <- f1
  _ <- shouldTrue( i == 2 )
  j <- f3  // f3 will only run if the predicate is true
} yield "Test1"
然后,它会自动生成更有意义的异常消息:

java.lang.Exception: i == 2 returns false
    at \path\to\example.scala:17

文档中也提到了这一点:当我再次查看时,没有。我认为在这里使用
recover
是可以的。如果您希望恢复只应用于基于筛选谓词的异常,那么您应该将
case
更改为
case ex:NoSuchElementException
其中
NoSuchElementException
来自
>java.util
.Jürgen:这是一个六个月前的问题,上面的代码是从REPL会话中提取的一个示例,因此它是为了清晰起见。您的评论是,您可以在Scala中的语句周围加括号?看不到您的贡献是什么。但是,如果f2因为“在你的
谓词
方法中,你最好使用
Future.successful(())
而不是
Future(())