Step 1 of 5 · Reading · ~3 min
Learn
Control Flow
Loops and Ranges
Kotlin's for loop does exactly one thing: it walks over something. There is no
for (i = 0; i < n; i++) form at all. What you walk over is usually a range.
Building ranges
| Expression | Produces | Note |
|---|---|---|
1..5 | 1 2 3 4 5 | both ends included |
1 until 5 | 1 2 3 4 | upper end excluded |
5 downTo 1 | 5 4 3 2 1 | counts backwards |
0..10 step 2 | 0 2 4 6 8 10 | any stride |
5..1 | nothing at all | an empty range, not an error |
fun main() {
for (i in 1..3) print(i)
println()
for (i in 1 until 3) print(i)
println()
for (i in 3 downTo 1) print(i)
println()
for (i in 5..1) print(i)
println("(empty)")
}
//> 123
//> 12
//> 321
//> (empty)
That last one is worth remembering. 5..1 does not quietly count downwards and does not throw
— it produces nothing, so the loop body never runs even once. If you want to go down, you have
to say downTo.
✓ / ✗ — the off-by-one
This is the single most common loop bug in Kotlin, because both forms read naturally in English.
✓ Sum of 1 through n, inclusive:
for (i in 1..n) total += i
✗ Stops one short — n itself is never added:
for (i in 1 until n) total += i
Rule of thumb: until is for indexes, which stop one before the size. .. is for values you
were handed.
Walking a collection
fun main() {
val crew = listOf("Ada", "Grace", "Alan")
for (name in crew) println(name)
for (i in crew.indices) println(i)
for ((i, name) in crew.withIndex()) println("$i -> $name")
}
//> Ada
//> Grace
//> Alan
//> 0
//> 1
//> 2
//> 0 -> Ada
//> 1 -> Grace
//> 2 -> Alan
crew.indices is exactly 0 until crew.size, which is a good reminder of why until is the
right tool for indexes.
while and do-while
while tests before the body runs; do-while runs the body once and tests afterwards, so it
always executes at least one time.
fun main() {
var countdown = 3
while (countdown > 0) {
print(countdown)
countdown -= 1
}
println("go")
}
//> 321go
Note the var. A counter or an accumulator is the honest use of var — a val cannot be
reassigned, so total += i on a val will not compile.
The library shortcut
Ranges and lists are ordinary values, so the standard library functions apply to them too:
fun main() {
println((1..5).sum())
println((1..5).count())
}
//> 15
//> 5
You will meet map, filter and the rest properly in the Lambdas and Higher-Order Functions
lesson. For now it is enough to know that sum() on a range exists and does what it says.
Your exercise
Sum 1 to N reads a positive integer and prints 1 + 2 + ... + n.
Either write the loop with a var total = 0 accumulator or call (1..n).sum() — both are fine,
and both are worth writing once. The mistake the grader catches is the off-by-one: the first
visible test feeds 5 and expects 15, but for (i in 1 until n) stops at 4 and prints
10. A hidden test feeds 100 and expects 5050, so the answer has to be computed rather than
hardcoded. Print the total alone, with no surrounding text.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…