What the code is supposed to do
The program has an array foods and should announce that it is hungry once, then say which food it will eat, one line per food:
I'm hungry!
I'll eat some pasta
I'll eat some burgers
I'll eat some pizza
The starter code compiles, but the output has the hungry line before every food:
val foods = Array("pasta", "burgers", "pizza")
for (food <- foods) {
println("I'm hungry!")
println(s"I'll eat some $food")
}
I'm hungry!
I'll eat some pasta
I'm hungry!
I'll eat some burgers
I'm hungry!
I'll eat some pizza
What goes wrong
Everything between the loop's braces is the loop body, and the body runs once for each element of foods. The array has three elements, so each statement in the body runs three times. The line println("I'm hungry!") sits inside the braces, so it runs three times as well.
The second line, println(s"I'll eat some $food"), is correct inside the loop: it needs food, which holds a different element on each pass. The hungry line doesn't use food at all. It should run one time, so it doesn't belong in the body.
The rule to remember
A statement belongs in the loop only if it must repeat for each element. A statement that should happen once goes outside. Where it goes decides when it runs:
- before the loop, it runs once, before the first element;
- after the loop, it runs once, after the last element.
The expected output has the hungry line first, so it goes before the loop.
Fixing it step by step
- Remove the hungry line from the loop body. Only the line that uses
foodstays inside. - Put it above the
forline. The program runs top to bottom, so it now prints before any food is handled. - Leave the second
printlnas it is. It already prints each food correctly.
The fixed code in Scala
val foods = Array("pasta", "burgers", "pizza")
println("I'm hungry!")
for (food <- foods) {
println(s"I'll eat some $food")
}
Scala details in these lines:
- Interpolation. The
sbefore the quote lets$foodinsert the current element. Without it, the text$foodwould be printed as it is. - The apostrophe.
I'mandI'llcontain a single quote, which is fine inside a string in double quotes.
Tracing the run
Follow the fixed program line by line:
- The array is created with three foods.
println("I'm hungry!")runs once and prints the first line.- The loop starts. With
foodequal to"pasta", it printsI'll eat some pasta. - The loop moves on:
foodbecomes"burgers", then"pizza", and each pass prints one line. - The array is exhausted, so the loop ends. Nothing follows it, so the program is done.
A useful check is to change the array. With four foods, the output still has one hungry line and four eating lines. With an empty array, Array[String](), the output is only I'm hungry!, because the body never runs. The number of times a line prints depends only on whether it is inside the loop.
Common mistakes
- Putting the line after the loop. It would print once, but at the end, after pizza, which doesn't match the expected order.
- Deleting the line from the loop but keeping a copy inside. The line would then print four times in total.
- Moving the wrong line. The food line needs the loop variable, which exists only between the braces, so moving it outside gives a
Not foundcompile error.
