Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 绘制未来地图的优雅备选方案[选项[…]_Scala - Fatal编程技术网

Scala 绘制未来地图的优雅备选方案[选项[…]

Scala 绘制未来地图的优雅备选方案[选项[…],scala,Scala,我有两个方法返回Future[Option[String]],如果第一个方法返回Future[None],则需要调用第二个方法。以下是我目前掌握的代码: def method1(): Future[Option[String]] = Future(None) def method2(): Future[Option[String]] = Future(Some("test")) val resultFuture = method1().flatMap(option => if (opti

我有两个方法返回
Future[Option[String]]
,如果第一个方法返回
Future[None]
,则需要调用第二个方法。以下是我目前掌握的代码:

def method1(): Future[Option[String]] = Future(None)
def method2(): Future[Option[String]] = Future(Some("test"))

val resultFuture = method1().flatMap(option =>
if (option.isDefined) { // Alternatives?
  Future(option)
} else {
  method2()
})

val durationSeconds = {
  import scala.concurrent.duration._
  import scala.language.postfixOps
  20 seconds
}
val result = Await.result(resultFuture, durationSeconds)
println(result) // Prints Some(test) as expected
我认为这个解决方案是有缺陷的,因为

  • 虽然没有实际的值转换,但是正在映射成功值(if部分)
  • 无需创建第二个未来(在if块中),以使编译器满意
  • 我试过了

  • method1().flatMap(option=>option.fold(method2)(value=>Future(option(value)))
    。但这也有同样的问题
  • option.orElse(…)
    ,但它需要返回一个
    option[B]
    而不是
    Future[option[B]

  • 请欣赏关于映射
    未来[None]
    而不显式映射/传递
    未来[Some[String]]

    的任何指针

    val resultFuture :Future[Option[String]] = method1().flatMap(
      _.fold(method2())(str => Future.successful(Some(str))))
    

    它仍然会重新包装已填充的
    选项
    ,但作为
    未来,它的开销会更小。successful()
    未来。apply
    创建一个新的未来,并将其安排在执行上下文上运行,这确实非常昂贵,因此您是对的,它不是最佳解决方案

    您可以使用
    Future.successful
    ,而不是
    Future.apply
    ,它创建已解析的
    Future
    ,这是一个非常便宜的操作。通过模式匹配和理解,您还可以使代码(可以说)更具可读性:

    for{
        m1 <- method1()
        result <- m1 match {
          case x @ Some(_) => Future.successful(x) //just lifts value into Future context
          case None => method2()
       }
    } yield result
    

    另一个您可能会考虑的解决方案是使用MaNad变压器<代码> optuts<代码>,这简化了嵌套的Maad堆栈的操作,如<代码>未来[选项[t] ] < /代码>。两者都提供了自己的

    option
    实现。下面是一个使用猫的示例:

    import cats.data.OptionT
    import cats.implicits._
    
    OptionT(method1()).orElseF(method2()).value
    
    稍微相关:退房
    import cats.data.OptionT
    import cats.implicits._
    
    OptionT(method1()).orElseF(method2()).value