Scala Future奇怪的编译错误

时间:2016-07-29 15:27:31

标签: scala asynchronous future

以下代码是真实代码的简化版本。我们“继承”了我们无法修改的域模型case object FutTestcase class FutTest。实际的域模型是从数据库提供的,所以我认为Future approach是有效的,但它会导致我不理解的问题。

import org.scalatest.FunSpec
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

case object FutTest {
  def create(sz: Int) = { FutTest(sz) }
}

case class FutTest(size: Int)

class FutureTest extends FunSpec {
  def one(v: Int): Future[FutTest] = {
    Future { FutTest.create(v) }
  }
  def two(t: FutTest) = {
    Future { FutTest.create(t.size) }
  }

  def compileError1: Future[FutTest] = {
    one(10).map(f => two(f))
  }

  def compileError2: Future[FutTest] = {
    for { o <- one(10) } yield (two(o))
  }
}

错误消息:

[INFO] Using incremental compilation
[INFO] Compiling 7 Scala sources and 5 .. target/test-classes...
[ERROR] domain.FutureTest.scala:25: type mismatch;
 found   : scala.concurrent.Future[domain.FutTest]
 required: domain.FutTest
[ERROR]     one(10).map(f => two(f))
[ERROR]                         ^
[ERROR] domain/FutureTest.scala:29: type mismatch;
 found   : scala.concurrent.Future[domain.FutTest]
 required: domain.FutTest
[ERROR]     for { o <- one(10) } yield (two(o))

我使用普通Int代替FutTest尝试了上述代码,一切都很好。为什么编译器会抱怨,如何在不触及现有域的情况下解决这个问题。

2 个答案:

答案 0 :(得分:5)

flatMap就是你想要的。

one(10).flatMap(f => two(f))

one(10).flatMap(two)

用于理解,

for { o <- one(10); t <- two(o) } yield t

答案 1 :(得分:4)

One()会返回Futuretwo()也会返回Future,因此您需要flatMap而不是map。当您映射到two()时,您的结果为Future[Future[FutTest]],需要展平。

否则

one(10).flatMap(f => two(f))

应该这样做。