Versuche, meinen Kopf wieder in Rust zu legen.
Also ich habe einen Typ, lass es ein newtype zum Zweck der Einfachheit sein:
%Vor% Und ich möchte Ord
implementieren.
Also tue ich:
%Vor%Wenn ich nun zwei Variablen meiner Typen vergleichen will, bekomme ich folgende Fehler:
%Vor% Nun, wenn ich PartialEq, Eq und PartialOrd (gt (), lt (), eq (), ge (), le () ...) implementiere, funktioniert alles gut. Was für ein Chaos. ABER: Wenn ich cmp
angegeben habe, können wir Funktionen wie lt()
und eq
! Das ist überflüssig! Ich mag das nicht!
Wenn ich in Dokumenten nachschaue, sehe ich das in der Definition von Ord:
%Vor% Nun sieht es so aus, als ob das Merkmal von Eq
und PartialOrd
erbt. Warum kann das Merkmal keine Standardimplementierungen für die erforderlichen Methoden aus den geerbten Merkmalen mithilfe der Funktion cmp
bereitstellen? Ich weiß nicht, wie das Erben von Merkmalen funktioniert (Googeln hat nicht geholfen, was beim Rotieren von Rost üblich ist), aber ich denke, das ist etwas, das möglich sein sollte.
Wie ist das in Rust? Ich hoffe nicht so ...
Nun, für Ihren speziellen Fall würde ich wahrscheinlich einfach #[derive]
verwenden:
Wenn Sie Ihre Ord
-Implementierung speziell behandeln müssen, müssen Sie diesen Code schreiben, da gibt es nichts, was uns rettet! Sie können immer noch Implementierungen für die anderen Merkmale ableiten, wenn es sinnvoll ist.
Der andere Teil Ihrer Frage ist mehrdeutig, also werde ich ihn auf beide Arten beantworten:
Warum kann
Ord
nicht automatisch mitPartialOrd
bereitgestellt werden?
Schauen wir uns die Dokumente für PartialOrd
und Ord
.
PartialOrd sagt: "Der Vergleich muss Antisymmetrie und Transitivität " erfüllen, während Ord sagt: "Typen, die eine Gesamtordnung " bilden. Das sind mathematische Begriffe und ich werde nicht so gut arbeiten, wie Wikipedia sie beschreiben wird.
Wir können jedoch Gleitkommazahlen als Beispiel verwenden. Floats haben einen speziellen Wert namens NaN
. Ein Vergleich mit diesem Wert ist schwierig. Zum Beispiel sind alle von 1.0 < NaN
, 1.0 == NaN
und 1.0 > NaN
falsch! Diese bilden keine Gesamtordnung, aber wir können immer noch einen Wert mit einem anderen vergleichen. Deshalb gibt es PartialOrd
- um solche Typen vergleichen zu können. Übrigens existiert PartialEq
aus ähnlichen Gründen.
Wir können Ord
in PartialOrd
nicht definieren, da wir nicht die entsprechenden Garantien für die zugrunde liegenden Typen haben. Dies ist Rust's Typsystem, das uns davor bewahrt, einen Fehler zu machen!
Warum kann
PartialOrd
nicht automatisch mitOrd
bereitgestellt werden?
Das Problem hier ist, dass mehr Typen PartialOrd
sind als Ord
. Wenn wir möchten, dass alles Ord
ist, dann könnten wir keine beliebigen Gleitkommavergleiche haben, weil sie keine vollständige Reihenfolge haben. Oder wir müssen aufgeben, wenn wir eine Gesamtbestellung haben und die Sicherheit verlieren, die es bietet.
wenn ich PartialOrd (gt (), lt (), eq (), ge (), le () ...) implementiere
Beachten Sie, dass PartialOrd
Standardimplementierungen hat, Sie müssen nur cmp
implementieren. Die anderen sind da für die Benutzerfreundlichkeit oder möglicherweise Leistungsaspekte.
Zunächst können Sie nur PartialOrd::partial_cmp
implementieren, da lt
, le
, gt
und ge
Standardimplementierungen haben. Wenn Sie Ord
implementieren, können Sie einfach cmp
wie gewohnt implementieren und partial_cmp
wird nur Some(self.cmp(other))
.
Wenn Sie jedoch nur an den Begriff Gleichheit und Ordnung eines Feldes delegieren möchten, ist es viel besser und einfacher abzuleiten:
%Vor%