What the code is supposed to do
The array languages holds "Python", "Java" and "JavaScript". The loop should print one sentence per language, with that language's name in it:
I think Python is cool!
I think Java is cool!
I think JavaScript is cool!
The starter code compiles and runs, but it prints the same line three times:
val languages = Array("Python", "Java", "JavaScript")
for (language <- languages) {
println("I think language is cool!")
}
I think language is cool!
I think language is cool!
I think language is cool!
What goes wrong
The loop itself is fine. It runs three times and the variable language holds a different value on each pass. The bug is in the message: everything inside double quotes is plain text. The characters l-a-n-g-u-a-g-e in the string are just letters, and the compiler does not look for a variable with that name. The string is the same on every pass, so the output is the same on every pass.
The loop variable is created, but nothing ever reads it. To use its value, the message has to be built from the variable rather than typed as fixed text.
Two ways to build the message
Scala offers string interpolation: put an s directly in front of the opening quote, and then $language inside the string is replaced by the variable's value. For a plain variable name, that is all it takes.
You can also join pieces with +:
println("I think " + language + " is cool!")
Both print the same text. Interpolation is the form the lesson uses, and the one most Scala code prefers because the sentence stays readable.
How the loop runs
It helps to follow the passes one at a time. On the first pass, language holds "Python", the body runs, and the message is built from that value. On the second pass the same variable holds "Java", and on the third "JavaScript". After the third element, the array has no more items, so the loop ends. The body is the same code every time; only the value of the loop variable changes, and that is why the message has to use the variable to differ.
The starter output is a useful clue for this kind of bug. When a loop prints the same line on every pass, the body is probably not reading the loop variable at all. When a loop prints different but wrong values, the variable is being used and the problem is somewhere else.
Fixing it step by step
- Find the part of the sentence that changes. Only the language name differs from pass to pass; the rest of the sentence is constant.
- Add the
sprefix before the opening quote so that Scala interprets$inside the string. - Replace the word
languagein the sentence with$language, which refers to the loop variable.
The fixed code in Scala
val languages = Array("Python", "Java", "JavaScript")
for (language <- languages) {
println(s"I think $language is cool!")
}
/* Explanation:
Notice that in the original code we didn't actually use the loop variable "language" inside the println() statement.
And so on each iteration, the println() printed "I think language is cool!" no matter if language = "Python" or language = "Java" etc.
The fix is to use the loop variable "language" with string interpolation to dynamically construct the message:
for (language <- languages) {
println(s"I think $language is cool!")
}
*/
It prints:
I think Python is cool!
I think Java is cool!
I think JavaScript is cool!
Details worth knowing about interpolation:
- The prefix is required. Without the
s,"I think $language is cool!"is an ordinary string, and the output contains a literal$language. - Braces for expressions.
$languagetakes a simple name. For a method call or any expression, use braces:s"${language.length} letters"prints6 lettersfor Python. Note that$languages(0)would not index the array: it inserts the array itself and then the text(0). Write${languages(0)}instead. - A literal dollar sign. Inside an
sstring, write$$to print one$.
Common mistakes
- Quoting the variable. Writing the variable's name inside plain quotes prints the name, not the value.
- Forgetting the
safter adding$. The dollar sign then shows up in the output. - Missing spaces with
+."I think" + language + "is cool!"printsI thinkPythonis cool!. The spaces belong inside the quoted pieces. - Changing the array. The array is correct as it is; the bug is only in how the message is built.
