迭代时将thunk转换为序列

时间:2014-12-02 13:20:34

标签: scala lazy-sequences

我有一个服务器API,它返回一个事物列表,并且一次只能包含25个项目。对于每个响应,我们都会获得一个项目列表,以及一个“令牌”,我们可以使用它来进行以下服务器调用以返回下一个25,依此类推。

请注意,我们使用的是一个用可靠的旧可变Java编写的客户端库,并且不能很好地适应所有Scala的功能组合模式。

我正在寻找一种方法来返回所有服务器项目的延迟评估序列,通过在本地项目列表用尽时使用最新令牌进行服务器调用。到目前为止我所拥有的是:

def fetchFromServer(uglyStateObject: StateObject): Seq[Thing] = {
    val results = server.call(uglyStateObject)

    uglyStateObject.update(results.token())

    results.asScala.toList ++ (if results.moreAvailable() then 
        fetchFromServer(uglyStateObject)
    else
        List())
}

但是,这个功能确实很热心。我正在寻找的是让++连接“严格序列”和“懒惰序列”,其中thunk将用于从服务器检索下一组项目。实际上,我想要这样的东西:

results.asScala.toList ++ Seq.lazy(() => fetchFromServer(uglyStateObject))

除了我不知道用什么代替Seq.lazy

到目前为止我见过的事情:

  • SeqView,但我看过不应该使用它的评论,因为它一直在重新评估?
  • Streams,但看起来抽象应该一次生成元素,而我想一次生成一堆元素。

我应该使用什么?

2 个答案:

答案 0 :(得分:0)

我还建议你看看scalaz-strem。这是一个小例子,它可能是什么样子

  import scalaz.stream._
  import scalaz.concurrent.Task

  // Returns updated state + fetched data
  def fetchFromServer(uglyStateObject: StateObject): (StateObject, Seq[Thing]) = ???

  // Initial state
  val init: StateObject = new StateObject

  val p: Process[Task, Thing] = Process.repeatEval[Task, Seq[Thing]] {
    var state = init
    Task(fetchFromServer(state)) map {
      case (s, seq) =>
        state = s
        seq
    }
  } flatMap Process.emitAll

答案 1 :(得分:0)

事实上,与此同时,我已经找到了一个稍微不同的答案,我发现它更具可读性(确实使用Streams):

def fetchFromServer(uglyStateObject: StateObject): Stream[Thing] = {
    val results = server.call(uglyStateObject)

    uglyStateObject.update(results.token())

    results.asScala.toStream #::: (if results.moreAvailable() then 
        fetchFromServer(uglyStateObject)
    else
        Stream.empty)
}

谢谢大家