scala - @tailrec 如何工作

标签 scala

我已经使用并阅读了 @tailrec注释具有尾递归方法。我已经浏览了许多解释它的链接。例如,它仅适用于自调用函数,不应被覆盖等。

到处都提到compiler optimizes .但是编译器做了什么魔术/概念来使它尾递归。对于下面的一个简单函数,编译器做了什么:

@tailrec def fact(acc: Int, n: Int): Int = {
  if (n <= 1) acc
  else fact(n * acc, n - 1)
}
fact(1,10)

我的意思是它是否将它转换成一个循环,重复调用它然后返回最终值?有没有解释它的论文链接

最佳答案

除了我对您的问题的评论(在此处重新粘贴代码):

  var acc = 1 
  var n = 10
start: 
  if (n <= 1) return acc 
  else { 
    acc = n * acc
    n = n - 1
    goto start
  }

我尝试编译 fact方法与我碰巧拥有的最近版本和 scalac -Xprint:all不知何故,编译器发出了 icode文件。所以这真的说明了它是如何优化尾调用的:
  // methods
  def fact(acc: Int (INT), n: Int (INT)): Int {
  locals: value acc, value n, value _$this
  startBlock: 1
  blocks: [1,2,3,4,5]

  1: 
    2   JUMP 2

  2: // huynhjl's comment: IF condition is here
    3   LOAD_LOCAL(value n)
    3   CONSTANT(1)
    3   CJUMP (INT)LE ? 3 : 4

  3: // huynhjl's comment: first branch of IF, will return acc
    3   LOAD_LOCAL(value acc)
    3   JUMP 5

  5: 
    2   RETURN(INT)

  4: // huynhjl's comment: else branch of IF, update acc and n and jump back
    4   LOAD_LOCAL(value n)
    4   LOAD_LOCAL(value acc)
    4   CALL_PRIMITIVE(Arithmetic(MUL,INT))
    4   LOAD_LOCAL(value n)
    4   CONSTANT(1)
    4   CALL_PRIMITIVE(Arithmetic(SUB,INT))
    4   STORE_LOCAL(value n)
    4   STORE_LOCAL(value acc)
    4   JUMP 2

  }

关于scala - @tailrec 如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17319412/

相关文章:

scala - Scala 反射中的去混叠类型

scala - 使用 scala fs2 文件流从文件中删除过滤行

scala - 使用宏重写 val 和 var 构造函数参数

scala - Scala 2.9将添加哪些新功能?

scala - Case.Aux在无形中是什么

scala - 可变参数函数被编译成什么?

scala - 在 Scala 中使用元组

python - Spark- 计算一列在另一列之后的百分比

scala - Scala中的映射类型

scala - 扩展函数缺少参数类型 匿名函数的参数类型必须完全已知。 (SLS 8.5) 预期类型为 :?