Swift 3.0:在数组或字典扩展中调用全局函数min(T,T)时出现编译器错误 [英] Swift 3.0: compiler error when calling global func min<T>(T,T) in Array or Dictionary extension
问题描述
从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
的扩展名时遇到相同的错误,而完全相同的代码在其他类型(例如String
或AudioBuffer
)的扩展名中可以正常编译:
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
):
查看Array
和Dictionary
的文档,我发现Sequence
上有名为public func min() -> Element?
和public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
的实例方法.虽然String
和AudioBuffer
都没有任何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屋!