Klarstellung zur Funktionssignatur und zum Versandverhalten in Julia

8

Ich habe einige Dinge in der Julia (1.2) REPL ausprobiert und mich auf etwas konzentriert, das ich über das Versenden nicht verstehe.


Ich habe zuerst dieses Ding ausprobiert, das so funktioniert, wie ich es erwartet hatte:

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

  • Das Aufrufen von f (3) funktioniert seitdem Int <: Int == true

  • Das Aufrufen von f ("Hallo") führt seitdem zu einem Fehler "MethodError: no method matching" String <: Int == false


Dann habe ich diese Methode ausprobiert und verstehe nicht, warum das Aufrufen in einigen Fällen funktioniert:

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

  • Das Aufrufen von f (3, 3) funktioniert (wie erwartet)

  • ABER f (3, "Hallo") funktioniert auch und löst keinen "MethodError: kein Methodenabgleich" aus ???

Ich dachte das (da T ein Int und U ein String wird) String <: Int == false???


Ich vermisse hier etwas ziemlich Unkompliziertes, aber ich kann es nicht finden ... Das ist also meine Frage, warum f (3, "Hallo") funktioniert ???


Außerdem habe ich dieses Codeausschnitt ausprobiert (ich habe versucht, die zweite Methodensignatur neu zu erstellen) und es schlägt korrekt fehl, wie ich erwartet hatte:

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

Test{Int, String} (Dies schlägt fehl, wie ich es mit "TypeError: in Type, in U, erwartet U <: Int64, bekam Type {String}" erwartet)

SnoopyDoowop
quelle
1
Ich kann Ihre letzte Definition von f () nicht reproduzieren Int64,String,false. Möglicherweise müssen Sie Julia neu starten, wenn Sie Methoden zu Funktionen hinzufügen. Verwenden Sie einfach ein neues Zeichen, z. B. hfür einen neuen Test. Zu Ihrer Frage: Es scheint, dass das System versucht, eine Lösung für die Typbeschränkung zu finden , und es T=Any, U=Any where U:<Tist eine. Wenn Sie einen konkreten Typ wie in Ihrem dritten Beispiel einführen, funktioniert er wie erwartet. Leute mit einem soliden Julia-Typ-Systemwissen werden bald eine richtige Antwort darauf geben.
Laborg
Oh! Du hast recht, ich musste Julia neu starten ... Meine Neudefinition mit T <: Int hat die letzte mit nur T nicht überschrieben (ohne Vorwarnung ...). Und Ihre Antwort auf die Suche nach Any als Lösung für T und U erklärt alles! Vielen Dank :)
SnoopyDoowop

Antworten:

4

Was hier passiert, ist, dass Tdies ein Datentyp und Uein beliebiger Supertyp einer Zeichenfolge sein kann. Damit sind die Voraussetzungen erfüllt. Das, was Sie dazu gebracht hat, dass ein String kein Subtyp von int ist, ist ein roter Hering, da kein konkreter Typ der Subtyp eines anderen ist.

Oscar Smith
quelle
Und warum steigt bei der Tupel-Definition stattdessen der Fehler an?
Antonello
3

Ok, dank Laborg scheint ich jetzt zu verstehen, was los war. Wenn wir diese Methode anwenden:

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

  • 'T' ist die "UnionAll" alias "Iterated Union" aller möglichen Arten von "a".
  • 'U' ist die "UnionAll", auch bekannt als "Iterated Union" aller möglichen Arten von 'b', die Subtypen von 'T' sind.

  • Was ich falsch verstanden habe, war die Tatsache, dass wenn (Beispiel) a :: Int, dann T einen übergeordneten abstrakten Typ von Typ von (a) annehmen kann. Da Int <: Any, dann ist T = Any eine gültige Lösung für den Versand.

  • Gleiches gilt für U = Any, da String <: Any.

Wir haben jetzt U <: T, das in Any <: Any == true aufgelöst wird, und die Methode wird aufgerufen!

Ich hoffe ich bekomme es :)

SnoopyDoowop
quelle
Sie machen. An diesem Punkt ist Ihre Antwort besser als meine.
Oscar Smith