Problem overview
The function printSum receives a vector of integers, nums, and should print the total of all its elements once. Called with vec![1, 2, 3], it should print 6, because 1 + 2 + 3 = 6. The code as given prints three lines instead: 1, 2 and 3.
The task is to fix the function without changing the code that calls it. There are two mistakes, and both are about where a line sits relative to the loop.
Finding the bugs
This is the buggy version:
fn printSum(nums: Vec<i32>) {
for num in &nums {
let mut sum = 0;
sum += num;
println!("{}", sum);
}
}
Tracing the loop by hand for 1, 2, 3 shows what happens on each pass:
- With
num = 1, a newsumis created at 0, becomes 1 and is printed. - With
num = 2, a newsumis created at 0 again, becomes 2 and is printed. - With
num = 3, the same happens and 3 is printed.
Bug 1: the accumulator is declared inside the loop
A variable declared in a block exists only inside it. The line let mut sum = 0; sits in the loop body, so every pass creates a new sum and the old one is gone. Nothing carries over from one number to the next, and the total can never build up. The declaration must go above the loop.
Bug 2: the print is inside the loop
The println! is also in the loop body, so it runs once per element. The total is only complete after the last element has been added, so the print belongs after the loop.
Fixing only the first bug still produces output, but the wrong one. With the declaration moved and the print left inside, the function prints the running totals 1, 3 and 6 on three lines instead of a single 6.
The solution in Rust
fn printSum(nums: Vec<i32>) {
let mut sum = 0;
for num in &nums {
sum += num;
}
println!("{}", sum);
}
fn mainFunction() {
printSum(vec![1, 2, 3]);
}
The Rust details worth noting:
- Borrowing in the loop.
for num in &numsiterates over references, sonumhas the type&i32. Rust allowssum += numwith a reference on the right-hand side of ani32addition, so no dereference is needed. Writingsum += *numgives the same result. - Why
&nums. Looping overnumsitself would move the vector into the loop. Borrowing it leavesnumsintact after the loop. - Type inference. The compiler gives
sumthe typei32, because it is added toi32values. - Names. The lesson's
printSumandmainFunctionare in camel case, where Rust style prefers snake case. This compiles with a style warning, and the lesson's tests look for these names, so keep them.
Edge cases and common mistakes
- An empty vector. The loop does not run, and the function prints
0. - Negative numbers.
vec![-5, 5, 10]prints10. The same code works unchanged. - Moving only one of the two lines. Both the declaration and the print have to move. Each one alone leaves a wrong output.
- Declaring
sumwithoutmut. It is a compile error, becausesum += numassigns to it. - Overflow. The total is an
i32. If the elements add up to more than 2,147,483,647, the optimized build wraps around silently, and a debug build panics.
Testing
vec![1, 2, 3]prints6.vec![]prints0.vec![-5, 5, 10]prints10.vec![7]prints7.
