具有多个参数列表的Scala方法中的尾递归

Edu*_*rdo 2 scala

我有以下功能:

  @tailrec
  def samePrefix[A](length: Int)(a: Vector[A], b: Vector[A]): Boolean = {
    if(length<1) true
    else{
      if(a(length-1)==b(length-1)) samePrefix(length-1)(a, b)
      else false
    }
  }
Run Code Online (Sandbox Code Playgroud)

在给定要检查的长度的情况下,检查两个向量是否具有相等的第一元素.

我想知道是否打电话的部分

samePrefix(length-1)(a, b)
Run Code Online (Sandbox Code Playgroud)

首先会创建一个函数对象samePrefix(length-1)然后应用(a,b)它,或者它只是递归地调用我的方法.

ghi*_*hik 5

让我们来看看...

$ scala
Welcome to Scala version 2.11.1
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.annotation._
import scala.annotation._

scala> @tailrec def curried(a: Int)(b: Int): Int = curried(a-1)(b-1)
curried: (a: Int)(b: Int)Int

scala> :javap curried
  ... irrelevant output removed ...       

  public int curried(int, int);
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=3
         0: iload_1       
         1: iconst_1      
         2: isub          
         3: iload_2       
         4: iconst_1      
         5: isub          
         6: istore_2      
         7: istore_1      
         8: goto          0

  ... irrelevant output removed ...
Run Code Online (Sandbox Code Playgroud)

如您所见,字节码中没有递归调用.相反,有一条goto 0指示循环的指令.这意味着尾调用优化已经发生.

您还会注意到,已编译的字节码中已将多个参数列表压缩为单个参数列表,因此不涉及任何中间函数.

编辑:实际上,我们没有必要检查字节码以100%确定该方法已使用TCO编译,因为@tailrec注释完全存在于此目的.换句话说,如果你@tailrec使用你的方法并且编译没有错误,你可以100%确定它是用TCO编译的.