Swift 变异函数作为第一个 class 值
Swift mutating Function as first class value
我可以有一个函数来交换数组的前两个元素:
func swapFirstTwo(array: inout [Int]) {
if array.count >= 2 {
array.swapAt(0, 1)
}
}
typealias Swapper = (inout [Int]) -> ()
// And I can have a variable = the function
let swapThem: Swapper = swapFirstTwo
// And it works like this:
var array = [1,2,3]
print(array)
swapThem(&array)
print(array)
// But I'm allergic to Global functions!
// It would be more swifty to have:
extension Array where Element == Int {
mutating func swapFirstTwo2() {
if count >= 2 {
swapAt(0, 1)
}
}
}
typealias Swapper2 = (inout [Int]) -> () -> ()
// But when I do this:
let swapThemAgain: Swapper2 = Array.swapFirstTwo2
// I get the error:
// Partial application of 'mutating' method is not allowed; calling the function has undefined behavior and will be an error in future Swift versions
var array2 = [1,2,3]
print(array2)
array2.swapFirstTwo2()
print(array2)
// This in fact works but I've tried similar things and sometimes they appear to be unstable.
// How can I achieve doing: array2.swapFirstTwo2() without getting the error?
这确实有效,但我尝试过类似的方法,但有时它们似乎不稳定。
还需要注意编译器警告。
我怎样才能做到 doing: array2.swapFirstTwo2() 而没有得到 warning/error?
您收到警告(很快就会在 Swift 5 模式下出错)的原因:
extension Array where Element == Int {
mutating func swapFirstTwo2() {
if count >= 2 {
swapAt(0, 1)
}
}
}
typealias Swapper2 = (inout [Int]) -> () -> ()
let swapThemAgain: Swapper2 = Array.swapFirstTwo2
是因为 inout
参数仅在传递给它们的调用期间有效,因此不能部分应用。
因此,如果您使用 &array2
调用返回的 (inout [Int]) -> () -> ()
,您将返回一个 () -> ()
,它现在具有对 array2
的无效引用。尝试调用该函数将产生未定义的行为,因为您正试图在有效的 window 之外改变 inout
参数。
此问题将得到解决 if/when unapplied instance methods get flat signatures,因为 Array.swapFirstTwo2
将计算为 (inout [Int]) -> ()
。
但与此同时,您可以改用闭包来解决此问题:
typealias Swapper2 = (inout [Int]) -> ()
let swapThemAgain: Swapper2 = { [=11=].swapFirstTwo2() }
var array2 = [1,2,3]
print(array2) // [1, 2, 3]
array2.swapFirstTwo2()
print(array2) // [2, 1, 3]
我可以有一个函数来交换数组的前两个元素:
func swapFirstTwo(array: inout [Int]) {
if array.count >= 2 {
array.swapAt(0, 1)
}
}
typealias Swapper = (inout [Int]) -> ()
// And I can have a variable = the function
let swapThem: Swapper = swapFirstTwo
// And it works like this:
var array = [1,2,3]
print(array)
swapThem(&array)
print(array)
// But I'm allergic to Global functions!
// It would be more swifty to have:
extension Array where Element == Int {
mutating func swapFirstTwo2() {
if count >= 2 {
swapAt(0, 1)
}
}
}
typealias Swapper2 = (inout [Int]) -> () -> ()
// But when I do this:
let swapThemAgain: Swapper2 = Array.swapFirstTwo2
// I get the error:
// Partial application of 'mutating' method is not allowed; calling the function has undefined behavior and will be an error in future Swift versions
var array2 = [1,2,3]
print(array2)
array2.swapFirstTwo2()
print(array2)
// This in fact works but I've tried similar things and sometimes they appear to be unstable.
// How can I achieve doing: array2.swapFirstTwo2() without getting the error?
这确实有效,但我尝试过类似的方法,但有时它们似乎不稳定。 还需要注意编译器警告。 我怎样才能做到 doing: array2.swapFirstTwo2() 而没有得到 warning/error?
您收到警告(很快就会在 Swift 5 模式下出错)的原因:
extension Array where Element == Int {
mutating func swapFirstTwo2() {
if count >= 2 {
swapAt(0, 1)
}
}
}
typealias Swapper2 = (inout [Int]) -> () -> ()
let swapThemAgain: Swapper2 = Array.swapFirstTwo2
是因为 inout
参数仅在传递给它们的调用期间有效,因此不能部分应用。
因此,如果您使用 &array2
调用返回的 (inout [Int]) -> () -> ()
,您将返回一个 () -> ()
,它现在具有对 array2
的无效引用。尝试调用该函数将产生未定义的行为,因为您正试图在有效的 window 之外改变 inout
参数。
此问题将得到解决 if/when unapplied instance methods get flat signatures,因为 Array.swapFirstTwo2
将计算为 (inout [Int]) -> ()
。
但与此同时,您可以改用闭包来解决此问题:
typealias Swapper2 = (inout [Int]) -> ()
let swapThemAgain: Swapper2 = { [=11=].swapFirstTwo2() }
var array2 = [1,2,3]
print(array2) // [1, 2, 3]
array2.swapFirstTwo2()
print(array2) // [2, 1, 3]