想象一下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)
}
}
此代码的明显问题是不可优化的递归:它将很快耗尽堆栈。有更有效的解决方案吗?
答案 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(())