我刚刚了解到,变异func只是一个带有第一个参数的curful func,因此下面的代码可以正常工作并将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
答案 0 :(得分:5)
一个有趣的注意事项是观察者在调用curry setter之前被称为 :
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)
最后两行中的一行应该发出错误,类似于let x = f.foo
。
答案 1 :(得分:1)
在最新接受的提案0042-flatten-method-type中,self
不再作为curried函数传递,因此在Swift 3中解决了这个问题