What the code is supposed to do
The function computeSum takes an integer n and returns the sum of the numbers from 0 up to n - 1. For computeSum(4) that is 0 + 1 + 2 + 3 = 6. The starter code returns 16 instead:
func computeSum(_ n: Int) -> Int {
var sum = 0
for i in 0..<n {
sum += n
}
return sum
}
What goes wrong
The loop runs the right number of times. The range 0..<n has n values, so for n = 4 it makes four passes, with i equal to 0, 1, 2 and 3. The mistake is what each pass adds. sum += n adds the parameter n, which stays 4 for the whole call:
- First pass:
sumbecomes 4. - Second pass: 8.
- Third pass: 12.
- Fourth pass: 16.
In general the function adds n to sum n times, so it returns n * n. The number that changes from pass to pass is the loop variable i, and the body never uses it. The compiler hints at this with a warning that the immutable value i was never used.
Fixing it step by step
- Keep the setup.
var sum = 0is correct: nothing has been added yet. - Keep the loop header.
0..<nproduces exactly the numbers to be added. - Add
iinstead ofn. The line becomessum += i.
The fixed code in Swift
func computeSum(_ n: Int) -> Int {
var sum = 0
for i in 0..<n {
sum += i
}
return sum
}
func mainFunction() {
print(computeSum(4))
}
Now the passes add 0, 1, 2 and 3, the running total goes 0, 1, 3, 6, and the program prints 6.
Swift details worth knowing:
- Half-open range.
0..<nstops beforen. Writing0...nwould includenand give 10 forcomputeSum(4), not 6. - Loop variables are constants.
igets a fresh value on each pass and can be read but not assigned. - Parameters are constants too.
ncan't be changed inside the function. - Return type. The function is declared
-> Int, soreturn summust produce anInt.
Reading the symptom
A wrong result is often a clue about the bug. Here the output, 16, is 4 * 4. That number is too regular to be an accident: it suggests the same value was added several times. A good habit is to check what each pass adds, by following a small input by hand or printing i and sum inside the loop. Printing would show i going 0, 1, 2, 3 while sum jumps by 4 each time, and the mismatch gives the bug away.
Hunting for variables that are declared but never used is also useful. Swift's warning about the unused i is the compiler noticing the same thing from the other side.
Edge cases and common mistakes
- Zero and one.
computeSum(0)andcomputeSum(1)both return 0, since the first range is empty and the second holds only 0. - Another value.
computeSum(10)returns 45, the sum of 0 through 9. - Mixing up the symptoms. With the bug,
computeSum(5)returns 25. A result equal ton * npoints straight to addingnin every pass. - Using the closed range. The task wants the sum up to
n - 1, so0...ngives a total that is too big byn.
Testing
computeSum(4)gives 6.computeSum(0)gives 0.computeSum(1)gives 0.computeSum(10)gives 45.
