Goo*_*rel 8 arrays swift swift-extensions swift3
从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"
}
}
Run Code Online (Sandbox Code Playgroud)
将相同的函数添加到扩展名时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(...)尽管它们具有完全不同的签名?
这是一个错误还是一个功能?我究竟做错了什么?如何min(T,T)在Array扩展程序内正确调用?
Ham*_*ish 10
我认为没有理由为什么编译器不能解析这个函数调用,因此我认为它是一个bug(它已经被提交 - 参见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
}
}
Run Code Online (Sandbox Code Playgroud)
在修复之前,一个简单的解决方案是在调用前加上它所在的模块的名称,以消除歧义,即你指的是顶层函数,而不是实例1.对于标准库,那是Swift:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return Swift.min(first, second)
}
}
Run Code Online (Sandbox Code Playgroud)
在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)
}
}
Run Code Online (Sandbox Code Playgroud)
虽然有趣的是编译器现在还会在尝试调用与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()
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,正如警告所说,你可以通过使用显式来使其静音self.:
extension Array where Element : Comparable {
func smallest() -> Element? {
return self.min()
}
}
Run Code Online (Sandbox Code Playgroud)
虽然什么是真的很好奇这个警告不会出现延伸到非STDLIB定义函数:
func foo(_ a: Int) {}
struct Foo {
func foo() {}
func bar() {
foo() // no warning...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1195 次 |
| 最近记录: |