在Xcode 9中为Swift 4进行光泽项目之后
我得到以下错误,我不知道
闭包元组参数'(key:_,value:_)'不支持解构
码:
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)
})
你的闭包有两个参数而不是一个(key
类型的Key
和value
类型的Value
)。这在Swift 3中有效,这要归功于一个称为解构的功能,编译器会自动将2个元素的元组转换为2个参数。
但是这个功能很奇怪,很少使用,并且在大多数情况下会产生意想不到的结果,所以它已经在Swift 4中删除了。 编辑:正如OOPer所指出的,此功能已在Swift 4测试版中暂时删除,但应在最终版本发布之前重新添加。
相反,你应该写:
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的这篇文章中得到了解决:
[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
有一些新的初始化器,它们采用Sequence
的(Key, Value)
对。例如:
我刚刚因使用enumerated().map()
而遇到此错误:
Closure元组参数不支持解构
我输入了代码:
["foo"].enumerated().map(
然后按住Enter直到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)的结果