<template>
<div class="headerNav">
<transition name="fade">
<div v-if="logo" class="logo" key="1"></div>
<div v-else class="logo two" key="2"></div>
</transition>
</div>
</template>
<script>
export default {
name: 'Navbar',
components: {
postFilter,
},
data() {
return {}
},
computed: {
logo() {
if (this.$route.name == 'Library' || this.$route.name == 'Profile') {
return false
} else {
return true
}
}
}
</script>
优化存在尾递归的函数。为什么编译器仍然不对其进行优化?
C编译器针对尾递归进行优化。您不必将方法标记为具有尾递归。编译器只是注意到最后一个操作是递归的。就是这样。
为什么这个貌似过多的关键字存在?我错过了什么吗?纯粹是为了方便编译器,而不是为了方便用户吗?
答案 0 :(得分:11)
关键字告诉编译器该函数的实现必须是尾部递归的,并且如果该函数实际上不是尾部递归的,则使编译器报告错误。当功能实现的更改导致它不再是尾部递归的,并导致性能意外下降(或由于堆栈溢出错误导致生产完全失败)时,它可以保护用户免受伤害。 >
答案 1 :(得分:2)
我将继续猜测这是为了能够更加有意地编写尾递归函数。通过显式地要求关键字,您将知道编译器优化肯定会发生(您不会猜测编译器是否成功优化了函数,或者在运行时是否会出现堆栈溢出),加上代码将不会如果您违反了用tailrec
编写的函数的尾部递归规则,则甚至可以进行编译,如文档所述:
要有资格使用tailrec修饰符,函数必须将其本身称为执行的最后一个操作。
答案 2 :(得分:0)
回想一下Kotlin的官方文档,它只是说:
当一个函数用tailrec修饰符标记并符合所需的形式时,编译器会优化递归,而留下一个快速,高效的基于循环的版本
强烈建议,如果不存在tailrec关键字,则不保证会转换为循环。
答案 3 :(得分:0)
基于@ szmb13 @yole答案的代码示例
尝试使用 n = 10000 运行此代码,如果遇到错误,请尝试添加 tailrec 关键字并再次运行
fun fibonacci(n: Int, a: BigInteger, b: BigInteger): BigInteger {
return if (n == 0) b
else fibonacci(n - 1, a + b, a)
}
您可以看到不同的