斯卡拉期货回调地狱
我多次阅读Scala期货,减少了回调问题。 我有一个开始看起来有问题的代码。
val a = Future(Option(Future(Option(10))))
a.map { b =>
  b.map { c =>
    c.map { d =>
      d.map { res =>
        res + 10
      }
    }
  }
} 
我怎样才能让这个代码更加平坦?
//编辑@againstmethod
for{
  b <- a
  c <- b
  d <- c
  res <- d
} yield res + 10
这段代码不会编译
  错误:(21,8)类型不匹配;  找到:需要选项[Int]: 
  scala.concurrent.Future [?] res < -  d 
  ^ 
你可以使用一个理解。 例如:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Stuff extends App {
  val result = for {
    f1 <- Future { 10 + 1 }
    f2 <- Future { f1 + 2 }
  } yield f2
  result.onComplete(println)
}
结果将是13。
  任何实现了正确的map和flatMap函数的类都可以在for 。 
如果你不介意另一个依赖项,你也可以使用像scalaz这样的库,并明确地使用monadic绑定来压扁东西(编辑一些选项类型来解决下面的注释):
import scalaz._
import Scalaz._
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.{Success,Failure}
object BindEx extends App {
  def f1(i: String): Future[Int] = Future { i.length }
  def f2(i: Int): Future[Option[Double]] = Future { Some(i / Math.PI) }
  def f3(i: Option[Double]): Future[Option[Double]] = Future { 
    i match {
      case Some(v) => Some(Math.round(v))
      case _ => None
    } 
  }
  val result = 
    Monad[Future].point("Starting Point") >>= 
    f1 >>= 
    f2 >>=
    f3
  result.onComplete { x => 
    x match {
      case Success(value) => println("Success " + value)
      case Failure(ex) => println(ex)
    }  
  }
  Await.result(result, 1 seconds)
}
最后,如果只有在所有成功独立的情况下都想要绑定并行操作,则可以使用scalaz应用程序构建器:
  val result = (
    Future { 10 + 10 } |@| 
    Future { 20 - 3 } |@| 
    Future { Math.PI * 15 }
  ) { _ + _ / _}
  println(Await.result(result, 1 seconds))
这将让所有3期货完成,然后对3个参数应用阻止。
其实答案非常简单。
for { 
a <- b
c <- a.get
} yield c.get + 10
  似乎已经足够了,因为当x.get + 10失败时(由于None + 10 ),未来就会失败。  所以它仍然可以使用简单的回退 
val f = for { 
a <- b
c <- a.get
} yield c.get + 10
f fallbackTo Future.successful(0)
我还没有使用它们,但它们应该正是你想要的:Monad变形金刚。
基本上,monad转换器需要一个Monad(如Future)并为其添加功能,例如Option提供的功能,并返回一个转换后的Monad。 我认为Scalaz甚至还有一个Option Monad变压器。 这应该允许你在Futures中使用嵌套的Options,并且仍然有一个用于理解的扁平代码结构。
见http://blog.garillot.net/post/91731853561/a-question-about-the-option-monad-transformer和https://softwarecorner.wordpress.com/2013/12/06/scalaz-optiont-monad - 变形器/举一些例子。
链接地址: http://www.djcxy.com/p/24669.html