Aclaración sobre la firma de funciones y el comportamiento de envío en julia


8

Estaba probando algunas cosas en el REPL de Julia (1.2) y me quedé pensando en algo que no entiendo sobre el envío.


Primero probé esto que funciona de la manera que esperaba:

f(a::T) where {T <: Int} = "Test"

  • Llamar a f (3) funciona desde Int <: Int == true

  • Llamar a f ("Hola") produce un error "MethodError: no hay coincidencia de método" desde String <: Int == false


Luego, probé este método, y no entiendo por qué llamarlo funciona en algunos casos:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • Llamar a f (3, 3) funciona (como esperaba)

  • PERO f (3, "Hola") también funciona y no arroja un "MethodError: ¿no coincide el método"?

¿Pensé que (ya que T se convierte en Int y U en String) String <: Int == false???


Supongo que me estoy perdiendo algo bastante sencillo aquí, pero no puedo encontrarlo ... Así que esta es mi pregunta, ¿por qué funciona f (3, "Hola")?


Además, probé este fragmento de código (intenté recrear la segunda firma del método) y falla correctamente como esperaba:

Test = Tuple{T, U} where {T, U <: T}

Test{Int, String} (esto falla como esperaba con "TypeError: in Type, en U, esperado U <: Int64, tengo Type {String}")


1
No puedo reproducir su última definición de f () regresando Int64,String,false. Es posible que deba reiniciar Julia si agrega métodos a las funciones. Simplemente use un nuevo personaje, por ejemplo, hpara una nueva prueba. A su pregunta: Parece que el sistema intenta encontrar alguna solución a la restricción de tipo, y T=Any, U=Any where U:<Tes una. Si introduce un tipo concreto como en su tercer ejemplo, funciona como se esperaba. Las personas con un conocimiento más sólido del sistema tipo Julia pronto darán una respuesta adecuada a esto.
Laborg

Oh! Tienes razón, necesitaba reiniciar Julia ... Mi redefinición con T <: Int no anuló la última con solo T (sin ninguna advertencia ...). ¡Y su respuesta sobre el sistema que encuentra Any como solución para T y U lo explica todo! Gracias :)
SnoopyDoowop

Respuestas:


4

Lo que sucede aquí es que Tpuede ser un tipo de datos y Upuede ser cualquier supertipo de cadena. Esto se cumplen las condiciones. Lo que te estaba tropezando con una cadena que no es un subtipo de int es un arenque rojo, ya que ningún tipo concreto es el subtipo de ningún otro.


¿Y por qué con la definición de Tuple en su lugar, aumenta el error?
Antonello

3

Ok, gracias a laborg parece que ahora entiendo lo que estaba pasando. Si tomamos este método:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • 'T' es el "UnionAll", también conocido como "Unión iterada" de todos los tipos posibles de 'a'.
  • 'U' es el "UnionAll", también conocido como "Unión iterada" de todos los tipos posibles de 'b' que son subtipos de 'T'

  • Lo que estaba malentendiendo era el hecho de que si (ejemplo) a :: Int, entonces T puede tomar un tipo abstracto padre de typeof (a). Como Int <: Any, entonces T = Any es una solución válida para el envío.

  • Lo mismo para U = Any desde String <: Any.

Así que ahora tenemos U <: T que se resuelve en Any <: Any == true, ¡y se llama al método!

Espero haberlo entendido :)


Tú lo haces. En este punto, la tuya es una mejor respuesta que la mía.
Oscar Smith
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.