我认为这是一个相当简单的尾递归函数。但是,@tailrec
告诉我。
@tailrec
def _next(continue : String, current : List[Long], first : Boolean ) : Stream[Long] = {
current match {
case head :: tail => head #:: _next(continue, tail, false) //this line breaks tailrec
case Nil if first => empty
case _ => {
val (nc, nl) = getIds(continue)
_next(nc, nl, true)
}
}
}
给我提供了
[error] could not optimize @tailrec annotated method _next: it contains a recursive call not in tail position
[error] case head :: tail => head #:: _next(continue, tail, false)
[error] ^
它可能与我从eclipse收到的隐式通知有关:- Implicit conversions found: _next(continue, tail, false) => consWrapper(_next(continue, tail, false))
,但遗憾的是,这并没有帮我解决问题。
我怎样才能解决这个问题,对于布朗尼点,哪里出错我认为这会拖尾?
答案 0 :(得分:4)
问题是,代码中的最后一项操作不是_next
的调用,而是Stream
缺点操作#::
。
一种解决方案是使用StreamBuilder
来构建您的流,并将此StreamBuilder
保留为累加器变量。
@tailrec
def _next(continue : String, current : List[Long], first : Boolean, acc: Stream.StreamBuilder[Long]) : Stream[Long] = {
current match {
case head :: tail =>
acc += head
_next(continue, tail, false, acc)
case Nil if first => acc.result
case _ => {
val (nc, nl) = getIds(continue)
_next(nc, nl, true, acc)
}
}
}
这不是特别有效 - 如果您使用StreamBuilder
而不是++=
向其添加整个集合,则+=
会更合适。因此,请考虑将代码更改为以下内容:
@tailrec
def _next(continue : String, current : List[Long], first : Boolean, acc: Stream.StreamBuilder[Long]) : Stream[Long] = {
current match {
case Nil =>
acc.result
case list =>
acc += list
val (nc, nl) = getIds(continue)
_next(nc, nl, true, acc)
}
}