[英]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
,因此实际上每次调用都会返回一个不同的函数 。 因此,匿名函数绝对不会调用自身 。
问题归结为这个简单的事实:匿名函数是匿名的。 因此,他们不可能直接调用自己:他们总是在调用其他可能返回自己的def
或val
,但是编译器并不知道。
因此,只有像@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.