Swift 3.0:在数组或字典扩展中调用全局函数min(T,T)时出现编译器错误 [英] Swift 3.0: compiler error when calling global func min<T>(T,T) in Array or Dictionary extension

查看:169
本文介绍了Swift 3.0:在数组或字典扩展中调用全局函数min(T,T)时出现编译器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Swift 2.2转换到3.0后,我的Array扩展名不再编译,因为它包含对全局标准库函数min<T>(T,T)的调用,并显示编译器错误extra argument in call.

After converting from Swift 2.2 to 3.0 my Array extension does not compile anymore, because it contains a call to global standard library function min<T>(T,T) and shows compiler error extra argument in call.

这是重现错误的简单方法:

Here's a simple way to reproduce the error:

extension Array {
    func smallestInt(first: Int, second: Int) -> Int {
        return min(first, second) // compiler error: "Extra argument in call"
    }
}

将相同的函数添加到Dictionary的扩展名时遇到相同的错误,而完全相同的代码在其他类型(例如StringAudioBuffer)的扩展名中可以正常编译:

I get the same error when adding the same function to an extension of Dictionary, while the exact same code compiles just fine in an extension of other types (e.g. String or AudioBuffer):

查看ArrayDictionary的文档,我发现Sequence上有名为public func min() -> Element?public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?的实例方法.虽然StringAudioBuffer都没有任何min(...)功能.

Looking at the documentation of Array and Dictionary, I find that there are instance methods on Sequence named public func min() -> Element? and public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?. While both String and AudioBuffer do not have any kind of min(...) function.

这可能是我无法调用全局函数的原因吗?编译器无法区分全局func min<T>(T,T)self.min(...),尽管它们具有完全不同的签名?

Is it possible that this is the reason why I can't call the global function? The compiler can't distinguish between global func min<T>(T,T) and self.min(...) although they have completely different signatures?

这是错误还是功能?我究竟做错了什么?如何在Array扩展名内正确调用min(T,T)?

Is this a bug or a feature? What am I doing wrong? How can I call min(T,T) correctly inside an Array extension?

推荐答案

我看不出编译器为何无法解决此函数调用的原因,因此我认为这是一个错误(已提交-请参见 SR-2450 ).

I see no reason why the compiler shouldn't be able to resolve this function call, therefore I would consider it a bug (it has already been filed – see SR-2450).

似乎在尝试调用具有相同名称但对给定类型(实例或静态)可从相同作用域访问的方法或属性明确不同的签名的顶级函数时,会发生这种情况.

It seems to occur whenever attempting to call a top-level function with the same name, but unambiguously different signature to a method or property that's accessible from the same scope in a given type (instance or static).

一个更简单的示例是:

func foo(_ a: Int) {}

struct Foo {

    func foo() {} // or static func foo() {}, var foo = 0, static var foo = 0

    func bar() {
        foo(2) // error: argument passed to call that takes no arguments
    }
}

直到修正,一种简单的解决方案是在调用之前为其所在模块的名称加上前缀,以消除您在引用顶级函数而不是实例函数的歧义.对于标准库,这是Swift:

Until fixed, a simple solution would be to prefix the call with the name of the module in which it resides in order to disambiguate that you're referring to the top-level function, rather than the instance one. For the standard library, that's Swift:

extension Array {
    func smallestInt(first: Int, second: Int) -> Int {
        return Swift.min(first, second)
    }
}


在Swift 4中,编译器对此错误有更好的诊断(尽管它仍然是错误,这是IMO的错误):


In Swift 4, the compiler has a better diagnostic for this error (though the fact that it's still an error is a bug IMO):

extension Array {
    func smallestInt(first: Int, second: Int) -> Int {
        // Use of 'min' refers to instance method 'min(by:)'
        // rather than global function 'min' in module 'Swift'
        // - Use 'Swift.' to reference the global function in module 'Swift'
        return min(first, second)
    }
}

尽管有趣的是,编译器将 now 还会警告您尝试调用与stdlib顶级函数同名的标准库方法:

Although what's interesting is that the compiler will now also warn on attempting to call a standard library method with the same name as a stdlib top-level function:

extension Array where Element : Comparable {

    func smallest() -> Element? {
        // Use of 'min' treated as a reference to instance method in protocol 'Sequence'
        // - Use 'self.' to silence this warning
        // - Use 'Swift.' to reference the global function
        return min()
    }
}

在这种情况下,如警告所述,您可以使用显式的self.将其静音:

In this case, as the warning says, you can silence it by using an explicit self.:

extension Array where Element : Comparable {

    func smallest() -> Element? {
        return self.min()
    }
}

尽管对此警告真正感到好奇的是,不会出现扩展到非stdlib定义的函数:

Although what's really curious about this warning is it doesn't appear to extend to non-stdlib defined functions:

func foo(_ a: Int) {}

struct Foo {

    func foo() {}

    func bar() {
        foo() // no warning...
    }
}

这篇关于Swift 3.0:在数组或字典扩展中调用全局函数min(T,T)时出现编译器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆