映射Scala期货

时间:2016-05-08 11:56:30

标签: scala

假设我有Future[Seq[Int]]我要转换为Future[Seq[String]]。目前我这样做:

 val futureSeqString = futureSeqInt.map( x => x.map(_.toString()))

这可行,但嵌套地图似乎有点尴尬。 Future[Option[Int]]的等效转换稍微好一点,但仍然不觉得我这样做是最好的方式:

val futureOptionString = futureOptionInt.map {       
  case Some(x) => x.toString(); 
  case _ => None;
}

有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:8)

双重嵌套需要双重映射,所以是的,在vanilla scala中,你所做的是正确的。

但是,如果我们将该理论考虑一下,ListFuture都会进行map操作,这会使它们成为Functors(这是过于简单化,但是忍受我)

两个Functors可以通用,因此您可以撰写Functor的{​​{1}}和Future的{​​{1}}来实现“联合”{ {1}}操作。

以下是使用cats的示例:

Functor

当然,您可以使用List执行相同操作。

map

奖励,无论嵌套的深度如何,您都可以使用相同的技术:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats._
import cats.std.future._
import cats.std.list._

// create a `Functor[Future[List]`
val futureListF = Functor[Future].compose(Functor[List])

val data = Future.successful(List(1, 2, 3))

// only one map!    
futureListF.map(data)(_.toString) // Future(List("1", "2", "3"))

答案 1 :(得分:5)

就个人而言,我没有看到嵌套地图有任何问题。你只需要更好地格式化和缩进它:

  future.map { seq =>
    seq.map(_.toString)
  }

有些人还发现for理解在这种情况下很有用(更重要的是,当你需要一起处理几个未来时)。

 for {
   seq <- future
 } yield seq.map(_.toString)