Scala未来结合

时间:2015-05-30 21:56:42

标签: scala

想象一下InputStream的变化:

trait FutureInputStream {
  //read bytes asynchronously. Empty array means EOF
  def read(): Future[Array[Byte]]
}

问题是如何为这样的流写入discardAll函数?这是我的解决方案:

//function that discards all input and returns Future completed on EOF
def discardAll(is: FutureInputStream): Future[Unit] = {
  val f = is.read()
  f.flatMap {
    case v if v.length == 0 =>
      Future successful Unit
    case _ =>
      discardAll(is)
  }
}

此代码的明显问题是不可优化的递归:它将很快耗尽堆栈。有更有效的解决方案吗?

1 个答案:

答案 0 :(得分:6)

您的解决方案没有任何问题。对discardAll(is)的调用是异步完成的。它不会发生在与前一次调用相同的堆栈帧中,因此不会发生堆栈溢出。

你可以看到天真的实现会发生什么:

trait FutureInputStream {
     var count = 0
     def read(): Future[Array[Byte]] = {
         if(count < 100000) {
             count += 1
             Future(Array(1))
         } else
             Future(Array())
     }
}

如果您要使用上述实例提供discardAll,那就没关系。

scala> val is = new FutureInputStream{}
is: FutureInputStream = $anon$1@255d542f

scala> discardAll(is).onComplete { println }
Success(())