Loops — while, for and ranges
Computers are astonishingly good at doing the same thing again. Learn while for "keep going until", for for "do this to each of these", and the two-dot-versus-until difference that causes more bugs than anything else in this part.
Nobody types the same line a hundred times
Suppose you want to print the numbers 1 to 100. You could write a hundred println lines. It would work. It would also take five minutes, contain at least one typo, and be unusable the moment somebody says "actually, make it 500".
A is code that repeats. You write the repeated part once and say how many times, or under what condition, to go round.
1for (i in 1..100) {
2 println(i)
3}Three lines. Change the 100 to 500 and you are done.
Think about walking up a staircase.
There are two ways to describe the climb. You can say "keep going up while there are still steps left" — you do not know how many there are, you just check each time whether you have reached the top.
Or, if you counted them on the way down yesterday, you can say "take twelve steps" — a fixed number, decided before you start.
Kotlin has both. is the first one: keep going while something is true. is the second: walk through a known set of things, one at a time, and stop by itself at the end.
while — keep going until something changes
1var lives = 3
2while (lives > 0) {
3 println("Lives: $lives")
4 lives = lives - 1
5}
6println("Game over")That prints Lives: 3, Lives: 2, Lives: 1, then Game over.
The in the brackets is checked before every pass, including the very first one. If it is false to begin with, the body never runs at all — a while can run zero times, and that is often exactly what you want.
Something inside the loop must eventually make the condition false. Delete the lives = lives - 1 line above and lives stays at 3 forever. That is an : the program does not crash, it just never finishes, and the Output panel fills with identical lines until you press Stop.
If a program seems to hang, an infinite loop is the first thing to suspect. Check that whatever the condition tests is actually changed somewhere inside the body.
for and ranges — walk through a known set
When you do know what to walk through, for is safer, because it cannot forget to stop:
1for (i in 1..5) {
2 println(i)
3}Read for (i in 1..5) as "for each number i in one to five". Each time round, i holds the next value. That prints 1, 2, 3, 4, 5.
1..5 is a . And here is the thing to burn into memory:
Two dots include both ends.
1..5is five numbers: 1, 2, 3, 4 and 5.
The one that catches everybody
Now the counterpart:
1for (i in 0 until 5) {
2 println(i)
3}That prints 0, 1, 2, 3, 4. Five numbers again — but it stops before the 5.
excludes its end value. Two dots include it. That single difference is the source of the , the most common counting bug in all of programming, and you will meet it for real in Lesson 1.10 when lists start at position 0.
Put the two side by side and say them out loud:
| Written | Gives | Count |
|---|---|---|
1..5 | 1, 2, 3, 4, 5 | 5 numbers |
1 until 5 | 1, 2, 3, 4 | 4 numbers |
0..5 | 0, 1, 2, 3, 4, 5 | 6 numbers |
0 until 5 | 0, 1, 2, 3, 4 | 5 numbers |
Two useful relatives:
1for (i in 5 downTo 1) {
2 println(i)
3}
4for (i in 0..10 step 2) {
5 println(i)
6}downTo counts backwards — 5, 4, 3, 2, 1. step 2 skips — 0, 2, 4, 6, 8, 10. Note that downTo also includes both ends.
When you simply want something to happen a fixed number of times and do not care about the counter, Kotlin has a shortcut:
1repeat(3) {
2 println("Hip hip")
3}That is three cheers with no counter to get wrong.
Stopping early, and skipping one
Two words work inside any loop:
breakleaves the loop immediately.continueskips the rest of this pass and goes round again.
1for (i in 1..10) {
2 if (i == 4) continue
3 if (i == 7) break
4 println(i)
5}That prints 1, 2, 3, 5, 6. Four is skipped, and at seven the loop stops for good.
The loop variable belongs to the loop
1for (i in 1..3) {
2 println(i)
3}
4println(i) // Unresolved reference: ii exists only inside the loop's . Once the loop ends, so does the name. It is also a each time round, so you cannot reassign it inside the body — if you need a counter you control, use while with your own .
Four loops, stepped through
- Open Pocket Studio, tap Projects, open KotlinLab, then open
Lab.kt. - Clear the inside of
mainand type in the program from the walkthrough above. - Tap Run. Count the lines in the Output panel. There should be twelve: three
Lives, threeStep, threeIndex, threeCountdown. - Change
for (i in 1..3)tofor (i in 1 until 3)and run again. Now there are only twoSteplines. One character of difference, one fewer pass. - Change
for (i in 3 downTo 1)tofor (i in 3..1)and run. Nothing at all is printed for that loop —3..1is an empty range. No error, no output. Silent bugs like this are whydownToexists. - Now make one on purpose: delete the
lives = lives - 1line and press Run. The output fills endlessly withLives: 3. Tap Stop, put the line back, and run again. - Finally add
println(i)after the closing bracket of the last loop, and run. Read theUnresolved reference: ierror — that is doing its job.
for (i = 0; i < 5; i++). Kotlin has no such form.for (i in 0 until 5). If you genuinely need full control of the counter, use a while loop with your own var.for loop that name is a fresh val on every pass, so it cannot be assigned to.step, continue, or a while loop with a var you control yourself.var above the loop and update it inside, if you need the value afterwards.in is not something Kotlin knows how to walk through — a single number, for instance, rather than a range.for (i in 1..n), not for (i in n).- A runs the same block repeatedly so you never type the same line twice.
- repeats while a is true, checking before each pass — so it can run zero times. Something inside must change the condition, or you get an .
- walks a and stops by itself.
1..5includes both ends.1 until 5stops one short. That difference is the waiting to happen.downTocounts backwards,stepskips,repeat(n)does something n times with no counter.breakleaves a loop;continueskips to the next pass.- Next: naming a whole block of steps so you can run it whenever you like — functions.