由于某些特殊原因,我想在一个大程序中去除所有@tailrec 的影响,但不想手动这样做,编译时是否有任何可选参数可以关闭尾递归优化?我只想在代码中保留@tailrec,但不想检查它并在编译时进行尾递归优化。这可能吗?
最佳答案
您可以使用编译器的 -g:notailcalls
选项。
来自文档:
-g:{none,source,line,vars,notailcalls}
"none" generates no debugging info,
"source" generates only the source file attribute,
"line" generates source and line number information,
"vars" generates source, line number and local variable information,
"notailcalls" generates all of the above and will not perform tail call optimization.
请注意,如文档所述,这还将启用调试信息生成。
一个例子:
import scala.annotation.tailrec
class A {
@tailrec
final def x(i: Int): Int = if(i == 0) {i;} else {x(i-1)}
}
javap -p -v A.class
of x
当“正常”编译时:
public final int x(int);
descriptor: (I)I
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=2, locals=2, args_size=2
0: iload_1
1: iconst_0
2: if_icmpne 7
5: iload_1
6: ireturn
7: iload_1
8: iconst_1
9: isub
10: istore_1
11: goto 0
相同,当使用 -g:notailcalls
编译时:
public final int x(int);
descriptor: (I)I
flags: ACC_PUBLIC, ACC_FINAL
Code:
stack=3, locals=2, args_size=2
0: iload_1
1: iconst_0
2: if_icmpne 9
5: iload_1
6: goto 16
9: aload_0
10: iload_1
11: iconst_1
12: isub
13: invokevirtual #12 // Method x:(I)I
16: ireturn
重要的一点是位置 13
上的 invokevirtual
。
请注意,顺便说一句,jwvh 谨慎地纠正了您对 @tailrec
的解释 - 它实际上并没有切换尾部优化,它唯一做的就是通知编译器如果它不能插入尾调用优化,则失败,它无论如何都会尝试。
关于scala - 有没有办法关闭Scala编译器的尾递归优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32324859/