Swift: 为什么我不能在 init() 之后链接变异函数?

Swift: Why can't I chain mutating functions after init()?

为什么我不能在初始化后立即修改已初始化的值类型?!

// using swift 5.5
struct Foo {
    var x: Int = 0
    mutating func add(_ y: Int) -> Foo {
        x += y
        return self
    }
}

var thisFails = Foo().add(42)   // ERROR! "Cannot mutate member on immutable value"
var alsoFails = (Foo().add(42)) // Same error

// test 1:
var test1 = Foo()
test1 = test1.add(13)   // Modifying 'test1' and assigning 'test1' is OKAY

// test 2:
_ = Foo()   // Creating something not assigned to variable is OKAY (but pointless)

// test 3:
extension Foo: CustomStringConvertible {
    var description: String { "Weird \(x)" }
}
print("Test3: \(Foo())") // Creating something not assigned to variable is OKAY

为什么语句 Foo().add(42) 有问题?

  1. 在堆栈上保存一些 space(对于 Foo)并初始化它(就像在测试#3 中一样);
  2. 将其用于函数 add(_);
  3. add(_)的返回值赋值给变量;

除非我错过了 Swift's Initialization documentation 中的某些内容,否则我不明白为什么会失败。

这是因为 Foo 是一个结构体,而结构体是一个 value type。这意味着您不能真正改变 Foo 的位置;你必须用另一个替换一个Foo。当您在 Foo 上调用 add 时,您实际上会得到一个 不同的 Foo(具有不同的 x),并且您将旧的替换为新的。这允许您这样做:

var test1 = Foo()
test1 = test1.add(13) // okay too
test1.add(14) // okay too

没关系,因为一直以来我们都有一个鞋盒,test1,我们可以赋值进去(var),这就是需要为了改变一个结构。 test1 持有一个 Foo,当我们通过说 add 来“改变”它时,我们丢弃了那个 Foo 并在其位置放置了一个不同的 Foo。

它的地方

但是 Foo().add(13) 没有给我们 任何可以分配给 的东西,所以你不能说出来。这是不连贯的。没有放置新 Foo 的“位置”。