【问题标题】:How can I annotate this tail recursive Scala function如何注释这个尾递归 Scala 函数
【发布时间】:2012-03-15 15:46:17
【问题描述】:

我有一个我知道是尾递归的函数。但是由于我定义它的方式,编译器抱怨该函数在非尾部位置具有递归调用。这就是函数。

@tailrec
def travel: (Int, List[Char]) => Int = {
    case (n,        Nil) => n
    case (n, '~' :: sls) => travel(0, sls)
    case (n, '^' :: sls) => travel(max(n-1,0), sls)
    case (n, '>' :: sls) => travel(n+1, sls)
    case (_,  s  :: sls) => throw new IllegalArgumentException("Illegal selector '" + s + "'")
}

我明白了

error: could not optimize @tailrec annotated method travel: it contains a recursive call not in tail position
def travel: (Int, List[Char]) => Int = {

如果我这样写,它可以正常工作。

@tailrec
def travel(n:Int, l:List[Char]): Int = (n,l) match {
    case (n,        Nil) => n
    case (n, '~' :: sls) => travel(0, sls)
    case (n, '^' :: sls) => travel(max(n-1,0), sls)
    case (n, '>' :: sls) => travel(n+1, sls)
    case (_,  s  :: sls) => throw new IllegalArgumentException("Illegal selector '" + s + "'")
}

我认为这与def: (Input) => Output = {} 类型声明风格有关。我使用它是因为它看起来比编写嵌套匹配或元组匹配更简洁。

【问题讨论】:

  • 我认为整个问题可以重新格式化为:“我们可以在匿名函数中添加@tailrec 注释吗?”
  • @paradigmatic - 这是一个不同的问题,但很好。不是注释,而是匿名函数进行尾递归调用的一种方式。 (它看不到自己的apply 方法。)

标签: scala tail-recursion tail-call-optimization


【解决方案1】:

两者不一样。在第一种情况下,方法产生一个函数,然后再次调用该方法(产生一个函数等)。也就是说,在第一种情况下,每次调用 travel 时,您都会创建一个 Function1[(Int, List[Char]), Int] 的新实例。不出所料,这不能转换为跳转指令。 (理论上可以,但分析会相当复杂,因为必须撤消所有这些对象的创建。)

第二种情况,只是一个调用自身的方法,可以转换成跳转。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 2016-01-14
    • 1970-01-01
    相关资源
    最近更新 更多