Kotlin:关于实例方法与扩展函数的`tailrec`
Kotlin: `tailrec` on Instance method vs Extension function
在下面的代码中,我看到了一个警告 no tail calls found
,但是同样的函数,当写成扩展函数时,没有那个警告。现在我很困惑我的 IDE 是错误的,还是我的扩展方法实际上不是尾递归的,或者编译器处理实例方法与扩展函数的方式有区别。
作为第二次警告
Recursive call is not a tail call
表示,这个调用是递归的,但不是尾调用。
这是因为调用函数时使用的是另一个实例作为目标(next
而不是 this
),所以 tailrec
对此没有真正的影响案件。如果将目标替换为 this
,编译器将停止发出任何警告。
我假设扩展函数编译时没有任何警告,因为它们被编译为静态(即非实例)函数,其中目标只是另一个参数,这意味着转换后的代码看起来(大致)像
@Nullable
public static final SLLNode2 getNodeForValue2(@NotNull SLLNode2 $this$getNodeForValue2, int valToFind) {
Intrinsics.checkParameterIsNotNull($this$getNodeForValue2, "$this$getNodeForValue2");
if ($this$getNodeForValue2.getValue() == valToFind) {
return $this$getNodeForValue2;
} else {
SLLNode2 var10000 = $this$getNodeForValue2.getNext();
return var10000 != null ? getNodeForValue2(var10000, valToFind) : null;
}
}
其中很明显包含递归尾调用。
但是,我不确定这种区别是有意的,因为编译扩展函数的方式应该是一个实现细节,而实例函数示例应该(?)等效优化。
编辑:看来这实际上是 bug.
在下面的代码中,我看到了一个警告 no tail calls found
,但是同样的函数,当写成扩展函数时,没有那个警告。现在我很困惑我的 IDE 是错误的,还是我的扩展方法实际上不是尾递归的,或者编译器处理实例方法与扩展函数的方式有区别。
作为第二次警告
Recursive call is not a tail call
表示,这个调用是递归的,但不是尾调用。
这是因为调用函数时使用的是另一个实例作为目标(next
而不是 this
),所以 tailrec
对此没有真正的影响案件。如果将目标替换为 this
,编译器将停止发出任何警告。
我假设扩展函数编译时没有任何警告,因为它们被编译为静态(即非实例)函数,其中目标只是另一个参数,这意味着转换后的代码看起来(大致)像
@Nullable
public static final SLLNode2 getNodeForValue2(@NotNull SLLNode2 $this$getNodeForValue2, int valToFind) {
Intrinsics.checkParameterIsNotNull($this$getNodeForValue2, "$this$getNodeForValue2");
if ($this$getNodeForValue2.getValue() == valToFind) {
return $this$getNodeForValue2;
} else {
SLLNode2 var10000 = $this$getNodeForValue2.getNext();
return var10000 != null ? getNodeForValue2(var10000, valToFind) : null;
}
}
其中很明显包含递归尾调用。
但是,我不确定这种区别是有意的,因为编译扩展函数的方式应该是一个实现细节,而实例函数示例应该(?)等效优化。
编辑:看来这实际上是 bug.