Start learning free

LESSON 120 OF 414 · FOR LOOPS - LOOPING OVER ARRAYS

Buggy Code: Moving a Statement After the Loop in Rust

Practice Read the full explanation

Inside the code editor we've tried to write a program that should print:

Hey, Andy
Hey, Mike
Hey, Mary
Let's start the class!

but it seems like we made some mistakes because when we run our code, it produces this output:

Hey, Andy
Let's start the class!
Hey, Mike
Let's start the class!
Hey, Mary
Let's start the class!

Assignment:

Your task is to fix our code such that it will print the desired output.

STEP 1 OF 1
    Ctrl + Enter to check

    RUST · FOR LOOPS - LOOPING OVER ARRAYS

    Buggy Code For Loops Execution Flow 2 in Rust, explained

    Problem overview

    The program should greet each student and then announce the start of class once, at the end:

    Hey, Andy
    Hey, Mike
    Hey, Mary
    Let's start the class!
    

    The code in the editor compiles and runs, but prints the announcement after every greeting:

    Hey, Andy
    Let's start the class!
    Hey, Mike
    Let's start the class!
    Hey, Mary
    Let's start the class!
    

    This is the starting code:

    let students = vec!["Andy", "Mike", "Mary"];
    for student in &students {
        println!("Hey, {}", student);
        println!("Let's start the class!");
    }

    What goes wrong

    The loop body is everything between the braces, and it runs once for each student. The vector has three students, so the body runs three times. Both println! calls are in the body, so each pass prints a greeting and then the announcement.

    The greeting is right where it is: it needs the loop variable student and must happen once per student. The announcement doesn't depend on any student. It says that class is starting, so it should happen a single time, after the last greeting.

    Execution flow

    A program runs from top to bottom. When the flow reaches a for, it runs the body for every item, and only then moves to the first line after the closing brace. That line runs once. So a statement placed after the closing brace is automatically "after all the greetings", which is what the task asks for.

    The mistake is about which side of one closing brace a line is on. Moving a single line across that brace changes how often it runs, from three times to one.

    The fix, step by step

    1. Take println!("Let's start the class!"); out of the loop body.
    2. Put it after the closing brace of the loop.
    3. Keep the greeting line inside, since it uses student.

    The reference solution is:

    let students = vec!["Andy", "Mike", "Mary"];
    for student in &students {
        println!("Hey, {}", student);
    }
    println!("Let's start the class!");

    Tracing it: the body prints Hey, Andy, Hey, Mike and Hey, Mary in turn. The loop ends, and the announcement prints once.

    Details and common mistakes

    • Putting the announcement before the loop. It then prints once, but first, so the order is wrong.
    • Leaving the line inside the braces and only changing its indentation. Rust ignores indentation here, and the line still runs three times.
    • Moving the greeting out of the loop instead of the announcement. The greeting uses student, which exists only inside the loop body, so the compiler would report an error that it can't find the value.
    • Forgetting that the loop variable is scoped to the loop. Anything after the closing brace can use students but not student.

    Testing

    With the three students above, the fixed program prints four lines. With an empty vector, declared as let students: Vec<&str> = vec![];, the body never runs and only the announcement prints, once. With five students, there are five greetings followed by a single announcement. The announcement count stays at one however many students there are, which is the property the fix gives you.

    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free