我刚刚了解到,mutation只是一个curried func,第一个参数为inout,所以下面的代码将工作并将firstName更改为“John”
- struct Person {
- var firstName = "Matt"
- mutating func changeName(fn: String) {
- firstName = fn
- }
- }
- var p = Person()
- let changer = Person.changeName
- changer(&p)("John")
- p.firstName
一个有趣的注意事项是,观察者在召集公民之前被召唤:
- struct Person {
- var firstName = "Matt"
- mutating func changeName(fn: String) {
- firstName = fn
- }
- }
- var p: Person = Person() {
- didSet {
- print("p was set")
- }
- }
- print("1: \(p.firstName)")
- let changer = Person.changeName
- print("2: \(p.firstName)")
- let setter = changer(&p)
- print("3: \(p.firstName)")
- setter("John")
- print("4: \(p.firstName)")
- p.changeName("John")
- print("5: \(p.firstName)")
打印:
- 1: Matt
- 2: Matt
- p was set
- 3: Matt
- 4: Matt
- p was set
- 5: John
所以似乎在inout结构体中获取setter方法会执行实际的突变。这通过inout参数如何在语义上工作来解释:当参数传递给函数时,它的值被复制到函数可以突变的地方。当函数返回时,该值将被复制回原始位置,触发setter观察者一次,该值是否改变。
当我们改变方式让预先填充的咖喱设定者:
- let setter = p.changeName
…编译器对象:
- error: partial application of 'mutating' method is not allowed
看来,编译器了解到关闭inout值是一个坏主意,因为它基本上是对值类型进行引用。
闭包可以随时更改struct的值,即使编译器假定它是不变的。为了防止这种不幸的情况,编译器只是禁止关闭inout。
您发现一个愚弄编译器并围绕诊断工作的情况。这似乎是一个错误,应该提交。
简短版本:
- struct Foo {
- mutating func foo() {}
- }
- var f = Foo()
- let m = Foo.foo
- let s = m(&f)
最后两行之一应该发出一个错误,类似于让x = f.foo。