tailrec Functions
Optimize recursion.
tailrec Functions is a free Kotlin Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, and your progress syncs across the web and the CoddyKit app. The Kotlin Academy course includes 4 lessons in total.
What Is Tail Recursion?
A function is tail-recursive when its recursive call is the very last operation. Kotlin can then optimize it into a loop, avoiding stack overflow.
tailrec fun countdown(n: Int) {
if (n < 0) return
println(n)
countdown(n - 1)
}
fun main() {
countdown(3)
}The tailrec Modifier
Add the tailrec modifier and the compiler rewrites the recursion as iteration, using constant stack space.
tailrec fun sum(n: Int, acc: Int = 0): Int {
if (n == 0) return acc
return sum(n - 1, acc + n)
}
fun main() {
println(sum(100))
}The Accumulator Pattern
To make recursion tail-form, carry results in an accumulator parameter so nothing remains to compute after the call.
tailrec fun factorial(n: Int, acc: Long = 1): Long {
if (n <= 1) return acc
return factorial(n - 1, acc * n)
}
fun main() {
println(factorial(10))
}Why the Call Must Be Last
If anything happens after the recursive call (like multiplying its result), the call is not in tail position and cannot be optimized.
tailrec fun length(s: String, acc: Int = 0): Int {
if (s.isEmpty()) return acc
return length(s.drop(1), acc + 1)
}
fun main() {
println(length("hello"))
}Non-Tail Recursion Counter-Example
This factorial is NOT tail-recursive because the multiply happens after the call returns. Marking it tailrec would warn.
fun badFactorial(n: Int): Long {
if (n <= 1) return 1
return n * badFactorial(n - 1)
}
fun main() {
println(badFactorial(5))
}Avoiding Stack Overflow
Deep recursion without tailrec can crash. With it, even large inputs run in constant stack space.
tailrec fun count(n: Int, acc: Int = 0): Int {
if (n == 0) return acc
return count(n - 1, acc + 1)
}
fun main() {
println(count(100000))
}Compiler Verification
If you mark a function tailrec but the call is not in tail position, the compiler emits a warning and does not optimize. Trust the warning.
tailrec fun gcd(a: Int, b: Int): Int {
if (b == 0) return a
return gcd(b, a % b)
}
fun main() {
println(gcd(48, 18))
}Tail Recursion vs Loop
A tailrec function compiles to roughly the same code as the equivalent loop, but expresses the algorithm recursively.
tailrec fun powerOfTwo(n: Int, acc: Long = 1): Long {
if (n == 0) return acc
return powerOfTwo(n - 1, acc * 2)
}
fun main() {
println(powerOfTwo(10))
}Multiple Parameters
Tail-recursive functions often pass along several state parameters, all updated in the recursive call.
tailrec fun fib(n: Int, a: Long = 0, b: Long = 1): Long {
if (n == 0) return a
return fib(n - 1, b, a + b)
}
fun main() {
println(fib(20))
}Reversing with tailrec
An accumulator can build up a result like a reversed string.
tailrec fun reverse(s: String, acc: String = ""): String {
if (s.isEmpty()) return acc
return reverse(s.drop(1), s.first() + acc)
}
fun main() {
println(reverse("kotlin"))
}A Practical Search
Iterative searches map cleanly to tail recursion.
tailrec fun indexOf(list: List<Int>, target: Int, i: Int = 0): Int {
if (i >= list.size) return -1
if (list[i] == target) return i
return indexOf(list, target, i + 1)
}
fun main() {
println(indexOf(listOf(5, 6, 7), 7))
}Quick Check
Test your understanding of tailrec functions.
Recap
You learned tailrec functions:
tailrecconverts tail-position recursion into a loop, avoiding stack overflow.- The recursive call must be the last operation.
- Use an accumulator parameter to reach tail form.
- The compiler warns when a function cannot be optimized.
tailrec fun sum(n: Int, acc: Int = 0): Int =
if (n == 0) acc else sum(n - 1, acc + n)
fun main() {
println(sum(50))
}Learn Kotlin with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “tailrec Functions” lesson free?
Yes — any 3 lessons of the Kotlin Academy learning path, including “tailrec Functions”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Kotlin Academy course includes 4 lessons in total.
What will I learn in “tailrec Functions”?
Optimize recursion. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Academy?
No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “tailrec Functions” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Academy lesson?
Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Infix Functions
- Building DSL-like APIs
- tailrec Functions
- When to Use Each