1

我有一个我认为是相当简单的尾递归函数。但是,@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)),但不幸的是,这并不能帮助我解决问题。

我该如何解决这个问题,并且,对于布朗尼点,我认为这会尾递归在哪里出错了?

4

1 回答 1

4

问题是代码中的最后一个操作不是调用_next,而是Streamcons 操作#::

一种解决方案是使用 aStreamBuilder来构建您的流并将其保留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)
    }
  }
于 2013-04-18T15:16:20.167 回答