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
我认为这个解决方案是有缺陷的,因为
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