scala - 无法优化@tailrec注释的方法循环: it contains a recursive call not in tail position

标签 scala recursion tail-recursion

我有以下递归函数,我想对其使用尾递归。但编译器提示我的实现出现以下错误:错误:(79, 7) 无法优化 @tailrec 带注释的方法循环:它包含不在尾部位置的递归调用 n 匹配 { ^

是不是因为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)
  }

最佳答案

是的,没错。要使其成为尾递归,您应该使用传递到递归中的显式累加器。

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

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

@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 =>
  }
}

关于scala - 无法优化@tailrec注释的方法循环: it contains a recursive call not in tail position,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33372871/

相关文章:

scala - 从哪里开始依赖类型编程?

scala - 通过反射判断类型是否为单例

java - mongodb scala 驱动程序 casbah 是否自动管理连接池

Python DFS,无法弄清楚为什么如果使用 append/pop() 返回列表为空但在递归调用中适用于 []+[]

functional-programming - Erlang 将一个列表附加/连接到另一个列表

recursion - F# 编译器可以优化这些相互递归的函数吗?

scala - 在 Scala 函数式编程中,是否有一种惯用的方式来映射状态?

c++ - 当函数调用中的值增加时程序工作正常,但如果我们在单独的行中增加值而不是调用函数,则会出错。为什么?

c# - 非无限递归字符串搜索中的 StackOverflowException

recursion - 实现最后一个非零而不延续