首页 文章

迭代时将thunk转换为序列

提问于
浏览
0

我有一个服务器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,但我使用've seen comments that it shouldn'因为它一直在重新评估?

  • Streams,但它们似乎是抽象应该一次生成元素,而我想一次生成一堆元素 .

我该怎么用?

2 回答

  • 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
    
  • 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)
    }
    

    谢谢大家

相关问题