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
- Take
println!("Let's start the class!");out of the loop body. - Put it after the closing brace of the loop.
- 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
studentsbut notstudent.
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.
