繁体   English   中英

可以执行尾递归

[英]Can function tail-recursive

我有一些递归代码,我想重构以使用Enumerator的尾递归,我可以简化该递归使其​​看起来像这样,请忽略此功能要实现的功能。

@tailrec
def doStuff: List[Int] => Int = {
      case Nil => 0
      case x :: xs => doStuff(xs)
    }

如果我摆脱了tailrec批注,它就可以正常工作,该结构看起来像是doStuff(doStuff(doStuff(..)))。 它将具有stackoverflow异常。

那么,如果它是一个函数,我如何使其尾递归

匿名函数不能设为尾递归。 让我们首先对您的代码进行非常简单的重写,以引入一个val来保存结果函数。

@tailrec
def doStuff: List[Int] => Int = {
  val result: List[Int] => Int = {
    case Nil => 0
    case x :: xs => doStuff(xs)
  }
  result
}

应该清楚的是,从那里开始, doStuff(xs) 并未调用匿名函数本身。 它正在调用doStuff方法,该方法返回要调用的函数。 更糟糕的是,由于它是一个def ,因此实际上每次调用都会返回一个不同的函数 因此,匿名函数绝对不会调用自身

问题归结为这个简单的事实:匿名函数是匿名的。 因此,他们不可能直接调用自己:他们总是在调用其他可能返回自己的defval ,但是编译器并不知道。

因此,只有像@dhg所建议的那样的适当def才真正是尾递归的。

现在,如果您真的想返回一个函数值(恰好是用尾递归实现),则可以使用theMethod _简单地将方法转换为函数。 因此,解决您最初的问题的方法如下:

val doStuff = {
  @tailrec
  def rec(list: List[Int]): Int = list match {
    case Nil => 0
    case x :: xs => rec(xs)
  }
  rec _
}

请注意,我们声明了适当的尾部递归方法rec ),然后使用rec _将其转换为函数值。

也许你是这个意思?

@tailrec
def doStuff(list: List[Int]): Int = list match {
  case Nil => 0
  case x :: xs => doStuff(xs)
}

那么,如果它是一个函数,我如何使其尾递归

你不能 我的意思是,您当然可以在Scala中编写尾部递归函数,但是它不会得到优化,因为它不会对您有所帮助。

Scala仅优化直接的尾递归方法调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM