无法优化@tailrec带注释的方法循环:它包含一个不在尾部位置的递归调用

时间:2015-10-27 16:05:36

标签: scala recursion tail-recursion

我有以下递归函数,我想在它上使用尾递归。但编译器抱怨我的实现有这个错误:Error:(79, 7) could not optimize @tailrec annotated method loop: it contains a recursive call not in tail position n match { ^

是因为for循环认为它不在尾部位置吗?

def dsl[N,E](qNodes:QNodeLike[N,E]*) = {
    val markers = scala.collection.mutable.Map.empty[String, N]
    @tailrec
    def loop(n:QNodeLike[N,E]):Unit = {
      n match {
        case QNode(head, kids:Seq[HalfEdgeLike[E,N]]) => {

          for(kid <- kids){
            kid match {
              case EmptyHalfEdge() =>
              case HalfEdge(e, n) => loop(n)
            }
          }
        }

        case QNodeMarker(head, marker, kids:Seq[HalfEdgeLike[E,N]]) => {
          markers.update(marker,head)
          for(kid <- kids){
            kid match {
              case EmptyHalfEdge() =>
              case HalfEdge(e, n) => loop(n)
            }
          }
        }
      }
    }

    loop(qNodes.head)
  }

2 个答案:

答案 0 :(得分:3)

是的,没错。为了使它是尾递归的,你应该使用一个显式的累加器,它被传递给递归。

但是,除非你有非常深度和窄树,否则你不太可能需要尾递归优化,因为运行时间会在你最终堆栈溢出之前变得非常大。

以下是如何对其进行尾部优化的粗略概念:

@tailrec
def loop(n:List[QNodeLike[N,E]]):Unit = {
  n match {
    case QNode(head, kids:Seq[HalfEdgeLike[E,N]]) :: rem => {
      kids match {
        case Nil =>
        case EmptyHalfEdge() :: rem2 => loop(rem2 ::: rem)
        case HalfEdge(e, n) :: rem2 => loop(n :: rem2 ::: rem)
      }
    }

    case QNodeMarker(head, marker, kids:Seq[HalfEdgeLike[E,N]]) :: rem => {
      markers.update(marker,head)
      kids match {
        case Nil =>
        case EmptyHalfEdge() :: rem2 => loop(rem2 ::: rem)
        case HalfEdge(e, n) :: rem2 => loop(n :: rem2 ::: rem)
      }
    }

    case Nil =>
  }
}

答案 1 :(得分:0)

是的,因为循环。 tailrec函数的结果必须是递归调用的结果。在您的情况下,结果是for语句的结果。