How a for loop works in Kotlin
A for loop runs a block of code once for each value in a sequence. Kotlin's for does not have the three-part header (start; condition; update) that you may know from C-style languages. Instead it reads like a sentence: for each i in this range, do the body.
for (i in 0 until 4) {
println("Hello world!")
}
This prints Hello world! on four lines. The loop variable i takes the values 0, 1, 2 and 3, one per pass.
The three jobs that a C-style header spells out are still there, but they are folded into the range:
- The start is the left side of
until. The loop variable begins at 0. - The end is the right side. The loop stops once the next value would reach 4.
- The step is 1 unless you say otherwise. After each pass
imoves to the next value on its own, so you never writei++.
What until means
start until end is a range that includes start and leaves out end. So 0 until 4 holds 0, 1, 2, 3, and it has exactly 4 values. That matches how counting works in most loops: starting at 0 and stopping before n gives you n passes.
The range 0..4 is different. The .. operator includes both ends, so it holds 0, 1, 2, 3, 4: five values. Confusing the two is the most common off-by-one mistake with Kotlin loops.
for (i in 0 until 3) print("$i ") // 0 1 2
println()
for (i in 0..3) print("$i ") // 0 1 2 3
println()
The first loop prints 0 1 2 and the second prints 0 1 2 3 .
What happens during the loop
For for (i in 0 until 4) the computer does this:
- Takes the first value of the range, 0, and gives it to
i. - Runs the body with
iequal to 0. - Takes the next value, 1, and runs the body again.
- Repeats for 2 and 3.
- Finds no values left (the next would be 4, which
untilexcludes) and exits the loop.
A range with no values, such as 0 until 0, runs the body zero times. That is not an error.
The loop variable
You do not declare i with val or var, and you do not give its type: Kotlin infers Int from the range. It exists only inside the loop, so using i after the closing brace is a compile error.
The loop variable is read-only. Inside the body, a statement such as i = 5 or i-- fails to compile with the error 'val' cannot be reassigned. This means you cannot accidentally change the counter from inside the body, and a loop over a range cannot be made infinite that way. If you need to skip values, change the range instead, as the following lessons show with step and downTo.
The exercise: print a message five times
The task is to print I promise to learn coding. five times with a for loop. It has two steps.
- Write the empty loop. Pick the variable name
iand a range with exactly five values.0 until 5holds 0, 1, 2, 3, 4, which is five values. The range0..5would hold six values and print the message six times. - Put the print inside. The body runs once per value, so a single
printlnin the body gives five lines of output.
The solution in Kotlin
for (i in 0 until 5) {
println("I promise to learn coding.")
}
The body does not use i. That is fine: here the variable only counts passes. The loop prints the sentence on five separate lines, because println ends its output with a line break.
Common mistakes
- Using
..when you meantuntil. The loop runs one time too many. - Writing semicolons in the header.
for (i = 0; i < 5; i++)is not Kotlin and does not compile. Usefor (i in 0 until 5). - Trying to change
iin the body. It is read-only. Use a different range or awhileloop if you need that control. - Leaving out the braces. Without
{ }, only the first statement after the header belongs to the loop. Any further statements below it run just once, after the loop. Always use braces until you are sure.
Key takeaways
for (i in a until b)visitsa,a + 1, and so on up tob - 1.a until bhasb - avalues, which makes it the natural choice when you want a given number of repetitions.- The loop variable is declared by the loop itself, is an
Inthere, and cannot be reassigned inside the body. ..includes its right end,untildoes not.