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
クロージャーは、1つのパラメータータイプElement
のみを取ります。ここで、Element
は、タプルのtypealias
にすぎません。
public typealias Element = (key: Key, value: Value)
したがって、クロージャーの最初のおよび唯一引数は、2つの要素のタプル(key
型のKey
およびvalue
型のValue
)でなければなりません。
さて、コードを見ると(Swift 3でコンパイルされます)、そうではないことがわかります。Swift 3でもこれが機能する理由を尋ねる必要があります。
try flatMap({ (key, value) in
return try transform(key, value)
})
クロージャーは、1つではなく2つの引数を取ります(key
型のKey
およびvalue
型のValue
)。これはSwift 3で機能します。これは、コンパイラが2要素のタプルを2つの引数に自動的に変換するdestructuringという機能のおかげです。
しかし、この機能は奇妙で、めったに使用されず、ほとんどの場合に予期しない結果をもたらすため、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単一タプルと複数引数の関数タイプを区別する 。
しかし、この提案に含まれるいくつかの機能は、いくつかの回帰を引き起こしました。これは evolution-announceメーリングリスト のこの投稿で対処されています
[Swift-evolution-announce] [Core team] Swift 4 のSE-0110ユーザビリティ回帰に対処
したがって、将来のベータ版またはGM Xcode 9のバージョンでは、コードは再びコンパイルされるでしょう。それまでは、この種の回避策を使用できます。
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()
を使用した結果、このエラーが発生しました。
クロージャータプルパラメーターは、構造化をサポートしていません
私はコードを入力しました:
["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ベータ(10L176w)を使用した結果