Start learning free

LESSON 112 OF 414 · FOR LOOPS - LOOPING OVER ARRAYS

Looping Over Arrays in Scala: Fixing the Greeting Loop

Practice Read the full explanation

Inside the code editor we've tried to write a for loop that greets every student in the students array.

So when we ran the code, we expected it to print:

Welcome, Andy
Welcome, Sally
Welcome, John

but it seems like we made some mistakes because when we run our code, it produces errors.


Assignment:

Your task is to fix our loop such that no errors will be produced and it will print the desired output.

STEP 1 OF 1
    Ctrl + Enter to check

    SCALA · FOR LOOPS - LOOPING OVER ARRAYS

    Buggy Code For Loops 1 in Scala, explained

    What the code is supposed to do

    The program has an array students and should greet every student, printing one line per name:

    Welcome, Andy
    Welcome, Sally
    Welcome, John
    

    The code you start with doesn't compile, so nothing is printed at all:

    val students = Array("Andy", "Sally", "John")
    
    for (name <- students) {
    }
    println(s"Welcome, $student")
    

    There are two separate mistakes, and fixing only one of them still leaves a broken program.

    Mistake 1: the print is outside the loop

    A for loop repeats the code between its braces, and only that code. The loop in the starter has an empty body, so it does nothing for each student. The println that follows the closing brace is an ordinary statement that runs once, after the loop has finished. Even if it compiled, you would get a single greeting instead of three.

    The fix is to move the println line between the braces, so that it runs once for every element of students.

    Mistake 2: the name doesn't exist

    In for (name <- students), the arrow <- reads "for each element taken from students", and the word before it, name, is the loop variable that holds the current element. But the message uses $student, a name that no declaration introduces. The compiler reports:

    Not found: student - did you mean students?
    

    Note the suggestion: students is the array, student is a different, undeclared name. The loop variable only exists between the loop's braces, so a line after the loop could not use it even if the spelling were right.

    There are two equally good fixes:

    • rename the loop variable to student, so it matches the message;
    • keep name and write $name in the message.

    Either way, the name in the pattern before <- and the name used in the body must be the same.

    Fixing it step by step

    1. Move the print inside the braces. Now it belongs to the loop body and runs for each student.
    2. Pick one name for the element. Here the loop variable becomes student, the name the message already uses.
    3. Check the message. The s in front of the quote turns on string interpolation, and $student is replaced by the current value.

    The fixed code in Scala

    val students = Array("Andy", "Sally", "John")
    
    for (student <- students) {
        println(s"Welcome, $student")
    }
    
    /* Explanation:
    
    There are two problems with the original code:
    1. The println() statement was placed outside the brackets, therefore Scala would consider it as not part of the loop.
    We'll have to move it inside the brackets like this:
    
    for (name <- students) {
        println(s"Welcome, $student")
    }
    
    2. If you run the code above, you'd still get an error.
    This is because inside the println() we use a variable named "student", which doesn't exist. The loop variable is named "name".
    There are two possible fixes to this:
    
    a. Use the loop variable "name" instead of "student" inside the println():
    for (name <- students) {
        println(s"Welcome, $name")
    }
    
    b. Change the loop variable's name to "student" instead of "name":
    for (student <- students) {
        println(s"Welcome, $student")
    }
    
    */
    

    A few Scala details are worth knowing here:

    • The generator. student <- students is called a generator. It is not an assignment you can reuse: the loop variable is a fresh val for each pass, so you can read it but not reassign it.
    • String interpolation. With the s prefix, $student inserts the variable's value. For anything more than a plain name, use braces: s"Welcome, ${student.toUpperCase}" prints Welcome, ANDY for the first student. Without the s, the text is printed literally, dollar sign included.
    • Braces mark the body. They show exactly which lines repeat. Scala 3 also accepts an indented block without braces, but with braces the end of the body can't be misread.

    Common mistakes

    • Fixing only one mistake. Moving the print inside the braces while the names still differ gives the same Not found error. Renaming the variable while the print stays after the loop also fails, because the variable doesn't exist outside the braces.
    • Mixing the array and the element. students and student differ by one letter. Interpolating $students would print the array object's text, something like [Ljava.lang.String;@7d417077, instead of a name.
    • Forgetting the s. println("Welcome, $student") prints the characters $student on every line.
    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free