可以使尾递归吗?
Can This Be Made Tail Recursive?
我正在访问一个 return 分页 JSON 响应的 HTTP 端点。 'meta.next' 的价值
在我的响应类型中指向响应的下一页。当这个值为null时,没有更多的页面
检索。
我正在使用 Spray IO 发出 HTTP 请求。我收集了每个感兴趣的条目
页面响应并将其与到目前为止收集的内容连接起来。当下一个变成
null,我return所有收集的条目。
我的问题:有没有办法让尾递归下面的 '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))
}
尾递归在这里并不适用。当您使用未来的组合器时,您不是在单个堆栈上操作。
具体来说,在每种情况下 getJson
立即 returns。通过使用 jsr.flatMap
,您正在注册一个回调,只有在收到 HTTP 请求的响应时才会调用该回调。因此,getJson
的下一次调用也将在此上下文中发生,即在隐式执行上下文提供的回调堆栈上。
因此,虽然递归仍在算法级别上发生,但它不会导致在一个(或任何)线程的堆栈上添加堆栈帧。
关于炸毁堆栈,您的代码很好。您想使用尾递归还有其他原因吗?
我正在访问一个 return 分页 JSON 响应的 HTTP 端点。 'meta.next' 的价值 在我的响应类型中指向响应的下一页。当这个值为null时,没有更多的页面 检索。 我正在使用 Spray IO 发出 HTTP 请求。我收集了每个感兴趣的条目 页面响应并将其与到目前为止收集的内容连接起来。当下一个变成 null,我return所有收集的条目。 我的问题:有没有办法让尾递归下面的 '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))
}
尾递归在这里并不适用。当您使用未来的组合器时,您不是在单个堆栈上操作。
具体来说,在每种情况下 getJson
立即 returns。通过使用 jsr.flatMap
,您正在注册一个回调,只有在收到 HTTP 请求的响应时才会调用该回调。因此,getJson
的下一次调用也将在此上下文中发生,即在隐式执行上下文提供的回调堆栈上。
因此,虽然递归仍在算法级别上发生,但它不会导致在一个(或任何)线程的堆栈上添加堆栈帧。
关于炸毁堆栈,您的代码很好。您想使用尾递归还有其他原因吗?