我有一个函数,它返回一个源自套接字的无限流的执行操作。
def f1(s:Stream[T]):Stream[T] = s map {...} filter {...}
我有另一个返回有限序列的方法,我想加入这个流。
def f2():Stream[T] = ...
这就是我要找的东西:
val a = f2#:::f1(s)
问题是,f2
需要一些时间来计算,f1
需要尽快输出值。我想将f2
包裹在Runnable
中,这样我就可以在不阻塞程序其余部分的情况下计算其值。
我希望a
的行为如下:如果正在计算f2
,则将其添加到f1
并继续输出该流的值。否则,请保持输出f1
的值。我该怎么办?
答案 0 :(得分:1)
您可以构建一个扩展Stream
的自定义类,并为您所需的语义定义所有必要的方法。在定义自定义语义时,使用此方法将为您提供最大的灵活性。然后,您甚至可以对Stream
进行丰富,使其具有withAsynPrefix
方法。以下是Iterator
的粗略版本,有点简单:
import scala.concurrent._
import scala.concurrent.duration._
import scala.util._
import scala.concurrent.ExecutionContext.Implicits.global
case class CombinedIterator[T](val iterator: Iterator[T], val prefix: Future[Iterator[T]]) extends Iterator[T] {
def hasNext: Boolean = iterator.hasNext || Await.result(prefix, Duration.Inf).hasNext
def next: T = prefix.value.collect {
case Success(pfx) if pfx.hasNext => pfx.next
}.getOrElse(iterator.next)
}
implicit class AsyncPrefixable[T](val iterator: Iterator[T]) extends AnyVal {
def withAsyncPrefix(prefix: Future[Iterator[T]]): Iterator[T] = CombinedIterator(iterator, prefix)
}
那么你可以这样做:
val iterator = Iterator.from(0).take(10000)
val prefix = Future { Thread.sleep(10); Iterator(-1) }
val iteratorWithPrefix = iterator.withAsyncPrefix(prefix)
iteratorWithPrefix.toList.indexOf(-1) //Run a few times, location can vary greatly within list