Swift 3.0:在数组或字典扩展中调用全局函数 min<T>(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
.
这是重现错误的简单方法:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return min(first, second) // compiler error: "Extra argument in call"
}
}
我在将相同的函数添加到 Dictionary
的扩展时遇到了同样的错误,而完全相同的代码在其他类型的扩展中编译得很好(例如 String
或 AudioBuffer
):
查看Array
和Dictionary
的文档,我发现Sequence
上有名为public func min() -> Element?
和public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
的实例方法。虽然 String
和 AudioBuffer
都没有任何类型的 min(...)
函数。
会不会是我无法调用全局函数的原因?编译器无法区分全局 func min<T>(T,T)
和 self.min(...)
尽管它们具有完全不同的签名?
这是错误还是功能?我究竟做错了什么?如何在 Array
扩展中正确调用 min(T,T)
?
我看不出为什么编译器不能解析这个函数调用,因此我认为这是一个错误(它已经被归档 – 参见 SR-2450)。
每当尝试调用具有相同名称的顶级函数时,似乎都会发生这种情况,但与方法或 属性 可以从给定类型(实例或静态)的相同范围访问的方法具有明显不同的签名).
一个更简单的例子是:
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
:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return Swift.min(first, second)
}
}
在 Swift 4 中,编译器对此错误有更好的诊断(尽管它仍然是错误的事实是 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)
}
}
尽管有趣的是,编译器 现在 还会对尝试调用与 stdlib 顶级函数同名的标准库方法发出警告:
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.
:
将其静音
extension Array where Element : Comparable {
func smallest() -> Element? {
return self.min()
}
}
虽然这个警告真正令人好奇的是它似乎 扩展到非 stdlib 定义的函数:
func foo(_ a: Int) {}
struct Foo {
func foo() {}
func bar() {
foo() // no warning...
}
}
从 Swift 2.2 转换为 3.0 后,我的 Array
扩展不再编译,因为它包含对全局标准库函数 min<T>(T,T)
的调用并显示编译器错误 extra argument in call
.
这是重现错误的简单方法:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return min(first, second) // compiler error: "Extra argument in call"
}
}
我在将相同的函数添加到 Dictionary
的扩展时遇到了同样的错误,而完全相同的代码在其他类型的扩展中编译得很好(例如 String
或 AudioBuffer
):
查看Array
和Dictionary
的文档,我发现Sequence
上有名为public func min() -> Element?
和public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
的实例方法。虽然 String
和 AudioBuffer
都没有任何类型的 min(...)
函数。
会不会是我无法调用全局函数的原因?编译器无法区分全局 func min<T>(T,T)
和 self.min(...)
尽管它们具有完全不同的签名?
这是错误还是功能?我究竟做错了什么?如何在 Array
扩展中正确调用 min(T,T)
?
我看不出为什么编译器不能解析这个函数调用,因此我认为这是一个错误(它已经被归档 – 参见 SR-2450)。
每当尝试调用具有相同名称的顶级函数时,似乎都会发生这种情况,但与方法或 属性 可以从给定类型(实例或静态)的相同范围访问的方法具有明显不同的签名).
一个更简单的例子是:
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
:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return Swift.min(first, second)
}
}
在 Swift 4 中,编译器对此错误有更好的诊断(尽管它仍然是错误的事实是 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)
}
}
尽管有趣的是,编译器 现在 还会对尝试调用与 stdlib 顶级函数同名的标准库方法发出警告:
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.
:
extension Array where Element : Comparable {
func smallest() -> Element? {
return self.min()
}
}
虽然这个警告真正令人好奇的是它似乎 扩展到非 stdlib 定义的函数:
func foo(_ a: Int) {}
struct Foo {
func foo() {}
func bar() {
foo() // no warning...
}
}