何时使用哪个函数
权衡取舍
何时使用哪个函数 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
两个工具,各司其职
中缀函数关注的是可读性;尾递归函数关注的是安全且高效的递归。它们解决的是互不相关的问题。
infix fun Int.add(o: Int) = this + o
tailrec fun sum(n: Int, acc: Int = 0): Int =
if (n == 0) acc else sum(n - 1, acc + n)
fun main() {
println(2 add 3)
println(sum(10))
}为流畅接口选择中缀函数
当省略点号和括号后调用读起来更好时,尤其是在 DSL 和构建二元组时,请考虑使用中缀函数。
fun main() {
val pair = "id" to 100
println(pair)
}为深度递归选择尾递归
当递归算法可能深入到足以导致栈溢出时,请使用尾递归。
tailrec fun count(n: Int, acc: Int = 0): Int =
if (n == 0) acc else count(n - 1, acc + 1)
fun main() {
println(count(50000))
}中缀函数的权衡
中缀函数会移除标点,这可能降低不熟悉它的读者的理解度,也会使优先级更复杂。请仅在它明确有帮助时使用。
infix fun Int.scaledBy(f: Int) = this * f
fun main() {
println(5 scaledBy 3)
}尾递归的权衡
将代码改为尾递归通常需要累加器,这可能不如普通循环直接。请在表达力与简单性之间进行权衡。
tailrec fun product(n: Int, acc: Long = 1): Long =
if (n <= 1) acc else product(n - 1, acc * n)
fun main() {
println(product(6))
}循环更简单的情况
如果普通的 for 或 while 循环比尾递归更清楚,请优先使用循环。递归是一种工具,而不是硬性要求。
fun sumLoop(n: Int): Int {
var total = 0
for (i in 1..n) total += i
return total
}
fun main() {
println(sumLoop(10))
}命名调用更清楚的情况
如果中缀名称并不能明显表示二元关系,普通的方法调用能更好地传达意图。
data class Temp(val c: Int) {
fun isWarmerThan(o: Temp) = c > o.c
}
fun main() {
println(Temp(30).isWarmerThan(Temp(20)))
}结合使用两者
这两个特性彼此独立;同一个程序可以使用中缀函数实现可读的调用,并使用尾递归实现安全的递归。
infix fun Int.upto(n: Int) = (this..n).toList()
tailrec fun last(list: List<Int>): Int =
if (list.size == 1) list[0] else last(list.drop(1))
fun main() {
println(last(1 upto 5))
}可读性检查清单
请思考:中缀函数是否让初学者更容易理解调用?尾递归是否能避免实际的栈溢出风险?如果不能,请优先使用普通函数和循环。
fun main() {
val r = (1..5).sum()
println(r)
}性能说明
尾递归可以在固定栈空间下提供类似循环的性能。中缀函数没有运行时开销;它纯粹是语法层面的特性。
tailrec fun pow(base: Int, exp: Int, acc: Long = 1): Long =
if (exp == 0) acc else pow(base, exp - 1, acc * base)
fun main() {
println(pow(2, 10))
}选择总结
中缀函数:流畅的单参数二元风格调用。尾递归:必须安全扩展的递归。二者都不是默认选择,而是经过考虑后的决定。
infix fun String.joinWith(o: String) = "$this-$o"
fun main() {
println("a" joinWith "b")
}快速检查
请检验您对何时使用各个特性的理解。
回顾
您学会了何时使用各个特性:
- 使用
infix实现流畅、易读的二元风格调用和 DSL。 - 使用
tailrec实现能够扩展且不会栈溢出的递归。 - 如果普通循环或命名函数更清楚,请优先使用它们。
- 这两个特性彼此独立,也可以结合使用。
infix fun Int.by(o: Int) = this * o
tailrec fun dec(n: Int): Int = if (n == 0) 0 else dec(n - 1)
fun main() {
println(3 by 4)
println(dec(1000))
}用 AI 导师学习 Kotlin — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「何时使用哪个函数」课时是免费的吗?
是的 — 「何时使用哪个函数」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「何时使用哪个函数」这节课中我会学到什么?
权衡取舍 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「何时使用哪个函数」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 中缀函数
- 构建类似 DSL 的 API
- tailrec 函数
- 何时使用哪个函数