提问人: 提问时间:10/8/2021 更新时间:10/8/2021 访问量:309
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)
- 在堆栈上节省一些空间(for a )并初始化它(就像在 test#3 中一样);
Foo
- 用它来做功能
add(_)
; - 从变量中获取返回值并赋值给变量;
add(_)
除非我错过了 Swift 初始化文档中的某些内容,否则我不明白为什么会失败。
答:
0赞
matt
10/8/2021
#1
这是因为 Foo 是一个结构体,而 struct 是一个值类型。这意味着您无法真正就地变异 Foo;你必须用另一个 Foo 替换一个 Foo。当你调用一个 Foo 时,你实际上会得到一个不同的 Foo(用不同的 ),然后你用新的替换旧的。这允许您执行此操作:add
x
var test1 = Foo()
test1 = test1.add(13) // okay too
test1.add(14) // okay too
这很好,因为一直以来我们都有一个鞋盒,我们可以将 () 分配给它 (),这是改变结构体所需的。 拿着一个 Foo,当我们通过说 来“变异”它时,我们扔掉了那个 Foo 并放置了一个不同的 Foo 来代替它。test1
var
test1
add
它的位置。
但是没有给我们任何可以分配的东西,所以你不能说出来。这是不连贯的。没有“地方”可以放置新的Foo。Foo().add(13)
评论
0赞
10/8/2021
甚至通过“扔掉”旧的 Foo 并更换它。如果给出一个 Foo,并产生一个全新的 Foo....然后,按照这个逻辑,“Foo().add()”应该可以工作。如果我们知道我们将通过以下调用将其替换为不同的 Foo,为什么还要费心将“Foo()”分配给鞋盒呢?Foo()
add()
0赞
10/8/2021
仅仅通过存在,Foo 就存在于内存中的某个地方,无论它是否有命名的鞋盒。所以我不明白为什么在突变之前或之后给它起一个名字会改变任何事情......毕竟,我们可以使用无名鞋盒(就像我的打印示例一样)。
0赞
matt
10/8/2021
我在这里不是要讨论某些计算机语言如何工作的形而上学,而是要帮助你有效地思考 Swift 语言如何工作的现实。
评论
let foo = Foo(x: 42)