Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 这是不是可以让尾巴递归?_Scala_Future_Spray_Tail Recursion - Fatal编程技术网

Scala 这是不是可以让尾巴递归?

Scala 这是不是可以让尾巴递归?,scala,future,spray,tail-recursion,Scala,Future,Spray,Tail Recursion,我正在访问一个返回分页JSON响应的HTTP端点。“meta.next”的值 在my response中,type指向响应的下一页。如果此值为null,则不再有页面 取回。 我正在使用Spray IO进行HTTP请求。我收集每个项目中感兴趣的条目 页面响应,并将其与迄今为止收集的内容连接起来。下一步什么时候开始 null,返回所有收集的条目。 我的问题是:有没有办法让tail下面的“getJson(…)”函数递归 case class JsonResponse(meta: Meta, item

我正在访问一个返回分页JSON响应的HTTP端点。“meta.next”的值 在my response中,type指向响应的下一页。如果此值为null,则不再有页面 取回。 我正在使用Spray IO进行HTTP请求。我收集每个项目中感兴趣的条目 页面响应,并将其与迄今为止收集的内容连接起来。下一步什么时候开始 null,返回所有收集的条目。 我的问题是:有没有办法让tail下面的“getJson(…)”函数递归

 case class JsonResponse(meta: Meta, items: List[Item])

 val pipeline: Future[HttpRequest => Future[JsonResponse]] = for (
    Http.HostConnectorInfo(connector, _) <-
    IO(Http) ? Http.HostConnectorSetup("somehost.com", port = 80)
  ) yield sendReceive(connector) ~> unmarshal[JsonResponse]


  // .....

  def getJson(relativeUrl: String)(implicit m: Monoid[Future[List[JsObject]]]) : Future[List[JsObject]] = {

    val jsr = pipeline.flatMap(_(Get(relativeUrl)))

    // Grab only those entries that we are interested in
    val objList = jsr.map(js => js.items.collect{ case o if(o.whatever.isDefined) => o.toJson.asJsObject })

    jsr.flatMap(js => js.meta.next.map(next => m.append(getJson(next), objList)).getOrElse(objList))
  }
case类JsonResponse(meta:meta,items:List[Item])
val管道:未来[HttpRequest=>Future[JsonResponse]]=for(
Http.HostConnectorInfo(连接器,_)解组[JsonResponse]
// .....
def getJson(relativeUrl:String)(隐式m:Monoid[Future[List[JsObject]]):Future[List[JsObject]={
val jsr=pipeline.flatMap((Get(relativeUrl)))
//只抓取我们感兴趣的条目
val objList=jsr.map(js=>js.items.collect{case o if(o.whater.isDefined)=>o.toJson.asJsObject})
jsr.flatMap(js=>js.meta.next.map(next=>m.append(getJson(next),objList)).getOrElse(objList))
}

尾部递归在这里并不适用。当您使用未来的组合器时,您不是在单个堆栈上操作

具体地说,
getJson
在任何情况下都会立即返回。通过使用
jsr.flatMap
您正在注册一个回调,只有在收到HTTP请求的响应时才会调用该回调。因此,
getJson
的下一次调用也将在此上下文中发生,即在e隐式执行上下文

因此,尽管递归仍在算法级别上进行,但它不会导致在一个(或任何)线程的堆栈上添加堆栈帧


关于清理堆栈,您的代码很好。您想使用尾部递归还有其他原因吗?

啊。谢谢!是的,我想使用尾部递归的唯一原因是担心清理堆栈。这可能会在返回之前处理很多页面。非常感谢您的清晰解释。我现在觉得有点驼背r没有意识到这一点,但也感到非常宽慰。不,担心。正如
Future
s作为新的通用异步执行原语一样强大,在一开始就很难掌握在所有不同的可能场景中执行是如何流动的。