I wrote two versions of code for a Swift programming exercise from an online programming exercise website. The exercise is as follows:
Find the difference between the square of the sum and the sum of the squares of the first N natural numbers. The square of the sum of the first ten natural numbers is (1 + 2 + ... + 10)² = 55² = 3025. The sum of the squares of the first ten natural numbers is 1² + 2² + ... + 10² = 385. Hence the difference between the square of the sum of the first ten natural numbers and the sum of the squares of the first ten natural numbers is 3025 - 385 = 2640.
The code for the first version is:
struct Squares {
let squareOfSum : UInt64
let sumOfSquares : UInt64
let differenceOfSquares : UInt64
init(_ number: UInt64) {
var sum = ((1 + number) * number) / 2
squareOfSum = sum * sum
sum = 0
for i in 1...number {
sum = sum + (UInt64)(i * i)
}
sumOfSquares = sum
differenceOfSquares = squareOfSum - sumOfSquares
}
}
let sqrs = Squares(5)
print(sqrs.differenceOfSquares)
It passes compilation and runs without problem.
The code for the second version is:
struct Squares {
let num : UInt64
lazy var squareOfSum: UInt64 = {
return ((1...num).reduce(0, +)).squared
}()
lazy var sumOfSquares: UInt64 = {
return ((1...num).map{$0.squared}).reduce(0, +)
}()
lazy var differenceOfSquares: UInt64 = {return squareOfSum - sumOfSquares }()
init(_ number: UInt64) {
num = number
}
}
extension Numeric {
var squared: Self {
return self * self
}
}
let sqrs = Squares(5)
print(sqrs.differenceOfSquares)
When the code is compiled, the compiler produces the following messages:
/tmp/0C9C2EC3-543D-486F-BCB0-D181EC48DC82.8NCVch/main.swift:25:7: error: cannot use mutating getter on immutable value: 'sqrs' is a 'let' constant
print(sqrs.differenceOfSquares)
^~~~
/tmp/0C9C2EC3-543D-486F-BCB0-D181EC48DC82.8NCVch/main.swift:24:1: note: change 'let' to 'var' to make it mutable
let sqrs = Squares(5)
^~~
var
If I change let into var for sqrs, as suggested by the compiler, the code will run well. Alternatively, if I change the type struct into class to make the object mutable, the code will also run well. However, in the code in my first version, there's not problem with the combination of a struct object and a let mutability delimiter. How come in the second version, these two become incongruent? While I don't know why, I suspect that it may have to do with the lazy initializers in the second version.
Can anyone please help explain this? Thank you very much in advance.