[翻译]  Closure tuple does not support destructuring in Xcode 9 Swift 4

[CHINESE]  关闭元组不支持Xcode 9 Swift 4中的解构


After the gloss project for Swift 4 in Xcode 9

在Xcode 9中为Swift 4进行光泽项目之后

I am getting following error which i have no idea

我得到以下错误,我不知道

Closure tuple parameter '(key: _, value: _)' does not support destructuring

闭包元组参数'(key:_,value:_)'不支持解构

Code:

码:

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)
        }))
    }
}

Error comes at this point try flatMap({ (key, value)in

此时出现错误尝试flatMap({(key,value)in

3 个解决方案

#1


13  

Let's start with the definition of flatMap for a dictionary which is the following:

让我们从字典的flatMap定义开始,如下所示:

func flatMap(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

You see that the transform closure takes only one parameter of type Element where Element is just a typealias for a tuple:

您会看到转换闭包只接受Element类型的一个参数,其中Element只是元组的一个类型:

public typealias Element = (key: Key, value: Value)

So the first and only argument of the closure should be a tuple of two elements (key of type Key and value of type Value).

所以闭包的第一个也是唯一的参数应该是两个元素的元组(Key类型的键和Value类型的值)。


Now, if you look at your code (which compiles in Swift 3), you will see that this is not the case, and you should be asking why does this even work in Swift 3.

现在,如果你查看你的代码(在Swift 3中编译),你会发现情况并非如此,你应该问为什么这甚至可以在Swift 3中运行。

try flatMap({ (key, value) in
    return try transform(key, value)
})

Your closure takes 2 arguments instead of one (key of type Key and value of type Value). This works in Swift 3 thanks to a feature called destructuring where the compiler will automatically transform a tuple of 2 elements into 2 arguments.

你的闭包需要2个参数而不是1个(Key类型的键和Value类型的值)。这在Swift 3中有效,这要归功于一个称为解构的功能,编译器会自动将2个元素的元组转换为2个参数。

But this feature is weird, rarely used and gives unexpected results most of the time so it has been removed in Swift 4.
Edit: As pointed out by OOPer, this feature has been temporarily removed in Swift 4 beta but should be re-added before the final version is out.

但是这个功能很奇怪,很少使用,并且在大多数情况下会产生意想不到的结果,所以它已经在Swift 4中删除了。编辑:正如OOPer所指出的,这个功能已经在Swift 4 beta中被暂时删除但是应该在之前重新添加最终版本已经发布。

Instead you should be writing:

相反,你应该写:

try flatMap({ tupleArgument in
    return try transform(tupleArgument.key, tupleArgument.value)
})

And your flatMap function becomes:

你的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)
    }))
}

#2


4  

It's a side-effect of this proposal for Swift 4:

这是Swift 4提案的副作用:

SE-0110 Distinguish between single-tuple and multiple-argument function types.

SE-0110区分单元组和多元函数类型。

But some features included in this proposal caused some regression which is addressed in this post of the evolution-announce mailing list:

但是这个提案中包含的一些功能引起了一些回归,这篇文章在evolution-announce邮件列表的这篇文章中得到了解决:

[swift-evolution-announce] [Core team] Addressing the SE-0110 usability regression in Swift 4

[swift-evolution-announce] [核心团队]解决Swift 4中的SE-0110可用性回归问题

So, you can expect in the future beta or GM version of Xcode9, your code would compile well again. Until then, you can use this sort of workaround:

因此,您可以预期在未来的Xcode9的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)
    }))
}

By the way, in Swift 4, Dictionary has some new initializers which take Sequence of (Key, Value) pair. For example:

顺便说一下,在Swift 4中,Dictionary有一些新的初始化器,它们采用Sequence(Key,Value)对。例如:

init(uniqueKeysWithValues: S)

init(uniqueKeysWithValues:S)

#3


1  

I just encountered this error as a result of using enumerated().map():

我刚刚使用enumerated()。map()遇到了这个错误:

Closure tuple parameter does not support destructuring

Closure元组参数不支持解构

I typed the code:

我输入了代码:

["foo"].enumerated().map(

And then kept pressing Enter until Xcode autocompleted the closure boilerplate.

然后按住Enter直到Xcode自动完成闭包样板。

The autocomplete seemingly has a bug that causes the above error. The autocomplete produces double-parenthesis ((offset: Int, element: String)) rather than single-parenthesis (offset: Int, element: String).

自动完成似乎有一个导致上述错误的错误。自动完成生成双括号((offset:Int,element:String))而不是单括号(offset:Int,element:String)。

I fixed it manually and was able to continue:

我手动修复它并且能够继续:

// 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"
}

Possibly the result of using Xcode 10.0 beta (10L176w)

可能是使用Xcode 10.0 beta(10L176w)的结果


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2018 ITdaan.com 粤ICP备14056181号