arrays - arreglos - string array in swift 3
Swift 3.0: error del compilador al llamar a la función global min<T>(T, T) en la extensión de matriz o diccionario (1)
No veo ninguna razón por la cual el compilador no pueda resolver esta llamada de función, por lo tanto, lo consideraría un error (ya se ha archivado; consulte SR-2450 ).
Parece ocurrir cada vez que se intenta llamar a una función de nivel superior con el mismo nombre, pero una firma inequívocamente diferente a un método o propiedad que es accesible desde el mismo alcance en un tipo dado (instancia o estático).
Un ejemplo aún más simple sería:
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
}
}
Hasta que se solucione, una solución simple sería prefijar la llamada con el nombre del módulo en el que reside para desambiguar que se refiere a la función de nivel superior, en lugar de la instancia.
Para la biblioteca estándar, eso es
Swift
:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return Swift.min(first, second)
}
}
En Swift 4, el compilador tiene un mejor diagnóstico para este error (aunque el hecho de que todavía sea un error es un error 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)
}
}
Aunque lo interesante es que el compilador ahora también advertirá al intentar llamar a un método de biblioteca estándar con el mismo nombre que una función de nivel superior 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()
}
}
En este caso, como dice la advertencia, puede silenciarlo utilizando un
self.
explícito
self.
:
extension Array where Element : Comparable {
func smallest() -> Element? {
return self.min()
}
}
Aunque lo realmente curioso de esta advertencia es que no parece extenderse a funciones no definidas por stdlib:
func foo(_ a: Int) {}
struct Foo {
func foo() {}
func bar() {
foo() // no warning...
}
}
Después de convertir de Swift 2.2 a 3.0, mi extensión
Array
ya no se compila, porque contiene una llamada a la función de biblioteca estándar global
min<T>(T,T)
y muestra un error
extra argument in call
compilador
extra argument in call
.
Aquí hay una manera simple de reproducir el error:
extension Array {
func smallestInt(first: Int, second: Int) -> Int {
return min(first, second) // compiler error: "Extra argument in call"
}
}
Recibo el mismo error al agregar la misma función a una extensión de
Dictionary
, mientras que el mismo código se compila perfectamente en una extensión de otros tipos (por ejemplo,
String
o
AudioBuffer
):
Al mirar la documentación de
Array
and
Dictionary
, encuentro que hay métodos de instancia en
Sequence
llamados
public func min() -> Element?
y
public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
.
Mientras que
String
y
AudioBuffer
no tienen ningún tipo de función
min(...)
.
¿Es posible que esta sea la razón por la que no puedo llamar a la función global?
El compilador no puede distinguir entre
func min<T>(T,T)
global
func min<T>(T,T)
y
self.min(...)
aunque tienen firmas completamente diferentes.
¿Es esto un error o una característica?
¿Qué estoy haciendo mal?
¿Cómo puedo llamar
min(T,T)
correctamente dentro de una extensión de
Array
?