我从一个在线编程练习网站为 Swift 编程练习编写了两个版本的代码。练习如下:
求和的平方与前 N 个自然数的平方和之间的差。前十个自然数的平方和为 (1 + 2 + ... + 10)² = 55² = 3025。前十个自然数的平方和为 1² + 2² + ... + 10² = 385。因此,前十个自然数之和的平方和前十个自然数的平方和之差为 3025 - 385 = 2640。
第一个版本的代码是:
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)
它通过编译并运行没有问题。
第二个版本的代码是:
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)
编译代码时,编译器会生成以下消息:
/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
如果我按照编译器的建议更改let
为var
for sqrs
,代码将运行良好。或者,如果我将类型更改struct
为class
使对象可变,代码也将运行良好。struct
但是,在我的第一个版本的代码中,对象和let
可变性分隔符的组合没有问题。怎么在第二个版本中,这两个变得不一致?虽然我不知道为什么,但我怀疑这可能与第二个版本中的惰性初始化器有关。
谁能帮忙解释一下?非常感谢您提前。