闭包元组不支持 Xcode 9 Swift 4 中的解构
Closure tuple does not support destructuring in Xcode 9 Swift 4
在 Swift 4 in Xcode 9
的光泽项目之后
我收到以下我不知道的错误
Closure tuple parameter '(key: _, value: _)' does not support
destructuring
代码:
extension Dictionary
{
init(elements: [Element]) {
self.init()
for (key, value) in elements {
self[key] = value
}
}
func flatMap<KeyPrime, ValuePrime>(_ transform: (Key, Value) throws -> (KeyPrime, ValuePrime)?) rethrows -> [KeyPrime:ValuePrime] {
return Dictionary<KeyPrime, ValuePrime>(elements: try flatMap({ (key, value) in
return try transform(key, value)
}))
}
}
此时出错try flatMap({ (key, value)in
让我们从字典 flatMap
的定义开始,如下所示:
func flatMap(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
您看到 transform
闭包只接受 一个 Element
类型的参数 ,其中 Element
只是一个 typealias
对于元组:
public typealias Element = (key: Key, value: Value)
所以闭包的第一个 和唯一的 参数应该是两个元素的元组(key
类型 Key
和 value
类型 Value
).
现在,如果您查看您的代码(在 Swift 3 中编译),您会发现情况并非如此,您应该问为什么这甚至在 Swift 3.
try flatMap({ (key, value) in
return try transform(key, value)
})
您的闭包采用 2 个参数而不是一个(key
类型 Key
和 value
类型 Value
)。由于名为 destructuring 的功能,这在 Swift 3 中有效,编译器会自动将 2 个元素的元组转换为 2 个参数。
但是这个功能很奇怪,很少使用,而且大多数时候会产生意想不到的结果,所以它在 Swift 4.
中被删除了
编辑:正如 OOPer 所指出的,此功能已在 Swift 4 beta 中暂时删除,但应在最终版本发布之前重新添加。
你应该这样写:
try flatMap({ tupleArgument in
return try transform(tupleArgument.key, tupleArgument.value)
})
您的 flatMap
函数变为:
func flatMap<KeyPrime, ValuePrime>(_ transform: (Key, Value) throws -> (KeyPrime, ValuePrime)?) rethrows -> [KeyPrime:ValuePrime] {
return Dictionary<KeyPrime, ValuePrime>(elements: try flatMap({ element in
return try transform(element.key, element.value)
}))
}
这是 Swift 4 提案的副作用:
SE-0110 Distinguish between single-tuple and multiple-argument function types.
但是此提案中包含的一些功能导致了一些回归,这在 evolution-announce mailing list 的 post 中得到解决:
[swift-evolution-announce] [Core team] Addressing the SE-0110 usability regression in Swift 4
因此,您可以期待在 Xcode 9 的未来 beta 或 GM 版本中,您的代码将再次编译良好。在那之前,您可以使用这种解决方法:
internal func flatMap<KeyPrime , ValuePrime>(_ transform: (Key, Value) throws -> (KeyPrime, ValuePrime)?) rethrows -> [KeyPrime : ValuePrime] {
return Dictionary<KeyPrime,ValuePrime>(elements: try flatMap({ pair in
let (key, value) = pair
return try transform(key, value)
}))
}
顺便说一下,在 Swift 4 中,Dictionary
有一些新的初始值设定项,它们采用 (Key, Value)
对中的 Sequence
。例如:
我刚刚因为使用 enumerated().map()
:
而遇到这个错误
Closure tuple parameter does not support destructuring
我输入了代码:
["foo"].enumerated().map
然后按 Enter 3 次,直到 Xcode 自动完成关闭样板文件。
自动完成似乎有一个导致上述错误的错误。自动完成生成双括号 ((offset: Int, element: String))
而不是单括号 (offset: Int, element: String)
.
我手动修复了它并且能够继续:
// Xcode autocomplete suggests:
let fail = ["foo"].enumerated().map { ((offset: Int, element: String)) -> String in
return "ERROR: Closure tuple parameter does not support destructuring"
}
// Works if you manually replace the "(( _ ))" with "( _ )"
let pass = ["foo"].enumerated().map { (offset: Int, element: String) -> String in
return "works"
}
可能是使用 Xcode 10.0 beta (10L176w)
的结果
我正在使用 Xcode 11.1 和 Swift 5,并且 运行 在使用 enumerated().map()
时出现此错误。我认为这个例子稍微简化了一些事情,但总的来说,这是为我解决的问题。真正的错误是编译器无法推断出 return 值:
// Correct Syntax
let resultModels: [ResultModel] = array.enumerated().map { index, model in
// code
}
// Results in the error Closure tuple does not support destructuring
let resultModels = array.enumerated().map { index, model in
// code
}
在 Swift 4 in Xcode 9
的光泽项目之后我收到以下我不知道的错误
Closure tuple parameter '(key: _, value: _)' does not support destructuring
代码:
extension Dictionary
{
init(elements: [Element]) {
self.init()
for (key, value) in elements {
self[key] = value
}
}
func flatMap<KeyPrime, ValuePrime>(_ transform: (Key, Value) throws -> (KeyPrime, ValuePrime)?) rethrows -> [KeyPrime:ValuePrime] {
return Dictionary<KeyPrime, ValuePrime>(elements: try flatMap({ (key, value) in
return try transform(key, value)
}))
}
}
此时出错try flatMap({ (key, value)in
让我们从字典 flatMap
的定义开始,如下所示:
func flatMap(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
您看到 transform
闭包只接受 一个 Element
类型的参数 ,其中 Element
只是一个 typealias
对于元组:
public typealias Element = (key: Key, value: Value)
所以闭包的第一个 和唯一的 参数应该是两个元素的元组(key
类型 Key
和 value
类型 Value
).
现在,如果您查看您的代码(在 Swift 3 中编译),您会发现情况并非如此,您应该问为什么这甚至在 Swift 3.
try flatMap({ (key, value) in
return try transform(key, value)
})
您的闭包采用 2 个参数而不是一个(key
类型 Key
和 value
类型 Value
)。由于名为 destructuring 的功能,这在 Swift 3 中有效,编译器会自动将 2 个元素的元组转换为 2 个参数。
但是这个功能很奇怪,很少使用,而且大多数时候会产生意想不到的结果,所以它在 Swift 4.
中被删除了
编辑:正如 OOPer 所指出的,此功能已在 Swift 4 beta 中暂时删除,但应在最终版本发布之前重新添加。
你应该这样写:
try flatMap({ tupleArgument in
return try transform(tupleArgument.key, tupleArgument.value)
})
您的 flatMap
函数变为:
func flatMap<KeyPrime, ValuePrime>(_ transform: (Key, Value) throws -> (KeyPrime, ValuePrime)?) rethrows -> [KeyPrime:ValuePrime] {
return Dictionary<KeyPrime, ValuePrime>(elements: try flatMap({ element in
return try transform(element.key, element.value)
}))
}
这是 Swift 4 提案的副作用:
SE-0110 Distinguish between single-tuple and multiple-argument function types.
但是此提案中包含的一些功能导致了一些回归,这在 evolution-announce mailing list 的 post 中得到解决:
[swift-evolution-announce] [Core team] Addressing the SE-0110 usability regression in Swift 4
因此,您可以期待在 Xcode 9 的未来 beta 或 GM 版本中,您的代码将再次编译良好。在那之前,您可以使用这种解决方法:
internal func flatMap<KeyPrime , ValuePrime>(_ transform: (Key, Value) throws -> (KeyPrime, ValuePrime)?) rethrows -> [KeyPrime : ValuePrime] {
return Dictionary<KeyPrime,ValuePrime>(elements: try flatMap({ pair in
let (key, value) = pair
return try transform(key, value)
}))
}
顺便说一下,在 Swift 4 中,Dictionary
有一些新的初始值设定项,它们采用 (Key, Value)
对中的 Sequence
。例如:
我刚刚因为使用 enumerated().map()
:
Closure tuple parameter does not support destructuring
我输入了代码:
["foo"].enumerated().map
然后按 Enter 3 次,直到 Xcode 自动完成关闭样板文件。
自动完成似乎有一个导致上述错误的错误。自动完成生成双括号 ((offset: Int, element: String))
而不是单括号 (offset: Int, element: String)
.
我手动修复了它并且能够继续:
// Xcode autocomplete suggests:
let fail = ["foo"].enumerated().map { ((offset: Int, element: String)) -> String in
return "ERROR: Closure tuple parameter does not support destructuring"
}
// Works if you manually replace the "(( _ ))" with "( _ )"
let pass = ["foo"].enumerated().map { (offset: Int, element: String) -> String in
return "works"
}
可能是使用 Xcode 10.0 beta (10L176w)
的结果我正在使用 Xcode 11.1 和 Swift 5,并且 运行 在使用 enumerated().map()
时出现此错误。我认为这个例子稍微简化了一些事情,但总的来说,这是为我解决的问题。真正的错误是编译器无法推断出 return 值:
// Correct Syntax
let resultModels: [ResultModel] = array.enumerated().map { index, model in
// code
}
// Results in the error Closure tuple does not support destructuring
let resultModels = array.enumerated().map { index, model in
// code
}