The problem: the same line, over and over
Programs often have to do the same thing for every item in a collection: greet each friend, print each fruit, add up each price. Without a loop, the only tool you have is to write the statement once per item.
Here is a program that greets four friends from an array:
val friends = arrayOf("Andy", "Mircea", "David", "Mary")
println("Hey, " + friends[0])
println("Hey, " + friends[1])
println("Hey, " + friends[2])
println("Hey, " + friends[3])
It prints one greeting per line:
Hey, Andy
Hey, Mircea
Hey, David
Hey, Mary
The code works. For four items, it is even tolerable. The problem shows when the data grows.
What goes wrong as the data grows
Look at the four lines. They are identical except for one number. That kind of repetition causes three problems:
- It does not scale. For 100 friends you would write 100 lines, and for a list that is read from a file, you would not know how many to write at all.
- It breaks easily. Copy and paste leaves traces. Forget to change one index and a friend is greeted twice. Write
friends[4]on a four-item array and the program stops with anArrayIndexOutOfBoundsException. - It is hard to change. If the greeting should become
"Hello, ", you must edit every line, and missing one leaves an inconsistent result.
Good code states a rule once. Here the rule is "greet every friend". A for loop lets you write exactly that, and the computer repeats it. The next lesson introduces the syntax. This lesson is about feeling the pain first, so that the loop makes sense when it arrives.
Two small Kotlin details
The example uses + to join a string and an array item. When a String is on the left, + converts what is on the right to text and joins them, so "Hey, " + friends[0] becomes Hey, Andy. It works with numbers too, and the order matters: "a" + 1 + 2 gives a12, because each + is applied from left to right to a string.
Kotlin also has string templates, which put a value inside a string with $. The line println("Hey, $name") inserts the variable name, and ${friends[0]} inserts the result of any expression. The exercise uses +, but templates are what you will usually write.
The exercise
The starting code has an array of four fruits:
val fruits = arrayOf("banana", "orange", "pear", "kiwi")
The task is to print I eat followed by each fruit, one per line, using only println and no loop:
- Read each item by its index. Array indices start at 0, so the four fruits are
fruits[0],fruits[1],fruits[2]andfruits[3]. - Join it to the text. The message is
"I eat ", with a space at the end so the fruit does not stick to the verb, followed by+and the fruit. - Write one
printlnper fruit, in index order.
val fruits = arrayOf("banana", "orange", "pear", "kiwi")
println("I eat " + fruits[0])
println("I eat " + fruits[1])
println("I eat " + fruits[2])
println("I eat " + fruits[3])
The output is:
I eat banana
I eat orange
I eat pear
I eat kiwi
Now picture the same code for 100 fruits. That is the cost a loop removes.
Common mistakes
- Starting at index 1. The first item is
fruits[0]. Starting at 1 skips the banana and runs off the end. - Forgetting the space in
"I eat ". Without it the output isI eatbanana. - Typing the fruit names instead of reading the array. The output may look the same, but the code no longer follows the data. If the array changes, the output would not.
Key takeaways
- Repeating one statement per item does not scale and invites copy-paste mistakes.
- Array items are read with
array[index], starting from 0. - A for loop replaces all those repeated lines with a rule written once.