尾递归失败(可能是因为隐式cons转换)

时间:2013-04-18 15:12:21

标签: scala implicit-conversion tail-recursion

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

我怎样才能解决这个问题,对于布朗尼点,哪里出错我认为这会拖尾?

1 个答案:

答案 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)
    }
  }