2015-06-26 23 views
22

durch das Buch Rust Lesen, stieß ich auf an interesting topic — divergent functions:Warum sollte ich divergierende Funktionen verwenden?

Rust einige spezielle Syntax für 'divergierende Funktionen' hat, die Funktionen, die nicht zurück:

fn diverges() -> ! { 
    panic!("This function never returns!"); 
} 

Eine divergierende Funktion kann als beliebiger Typ verwendet werden:

let x: i32 = diverges(); 
let x: String = diverges(); 

Was wären die Anwendungsfälle einer divergenten Funktion? Das Buch sagt, dass

panic!() der aktuelle Thread der Ausführung bewirkt, dass mit der gegebenen Nachricht zum Absturz bringen. Da diese Funktion zu einem Absturz führen wird, wird es nie Rückkehr, und so hat es die Art !

den Sinn macht, aber ich kann nicht glauben, wo sonst eine divergierende Funktion von Nutzen sein würde und es scheint, sehr lokalisiert auf nur panic!. Ich weiß, dass es einige nützliche Szenarien dafür geben muss, warum sie divergierende Funktionen eingeführt haben. Wo würde ich wahrscheinlich divergierende Funktionen in Rust sehen?

Antwort

31

Es mehrere Verwendungen hat. Es kann für Funktionen verwendet werden, die das Programm in Panik versetzen oder das Programm verlassen. panic!() selbst ist eine solche Funktion, aber es kann auch auf Funktionen angewendet werden, die panic!() umhüllen, wie das Ausgeben detaillierterer Fehlerinformationen und dann Panik.

Es kann auch für Funktionen verwendet werden, die nie zurückkehren. Wenn eine Funktion in eine Endlosschleife wie die Hauptschleife eines Servers übergeht und daher niemals zurückkehrt, könnte sie auf diese Weise definiert werden.

Eine andere mögliche Verwendung wäre ein Wrapper um den Unix exec family of functions, in dem der aktuelle Prozess durch den aktuellen Prozess ersetzt wird.

Es ist nützlich, einen solchen Typ zu haben, weil er mit allen anderen Typen kompatibel ist. Um typsicher zu sein, muss Rust sicherstellen, dass alle Zweige einer match oder if Anweisung den gleichen Typ zurückgeben. Wenn jedoch einige Zweige nicht erreichbar sind oder einen Fehler anzeigen, müssen Sie einen Fehler erzeugen, der mit dem von den anderen Zweigen zurückgegebenen Typ übereinstimmt. Da ! mit allen Typen vereint ist, kann es in jedem Fall verwendet werden.

Es gibt ein interesting RFC (und discussion) zur Zeit, die (teilweise) für expanding the places where ! can be used argumentiert Streiten, dass es als ein vollwertiges Typ wie () ist behandelt werden sollte; ! ist ein Typ ohne Werte, der mit allen anderen Typen vereinheitlicht, während () ein unterschiedlicher Typ mit einem einzelnen Wert ist. Ich bin mir nicht sicher, ob ich dem vollständigen RFC zustimme, aber die Diskussion, ! als einen vollwertigen Typ zu behandeln, ist interessant und ich denke, dass er separat vom Rest des RFC vorgeschlagen werden könnte.

aktualisieren: Da ich die oben geschrieben, der Teil des RFC über ! zu einer vollwertigen Art der Förderung war split into a separate RFC and merged und ist in the process of being implemented (derzeit in jeder Nacht hinter einem Feature-Gate baut). Als vollwertiger Typ kann er in mehreren Kontexten verwendet werden, wie z. B. in Result<T, !>, das ein Ergebnis anzeigt, das niemals fehlschlagen kann, oder Result<!, E> als eines, das niemals erfolgreich sein kann. Diese sind nützlich in generischen Kontexten; Wenn Sie eine Eigenschaft haben, die eine Methode erfordert, um ein Ergebnis zurückzugeben, aber für diese bestimmte Implementierung nur erfolgreich sein kann, müssen Sie keinen Dummy-Fehlertyp eingeben.

12

Wie Sie aus dem Buch zitiert haben, wird Rust bottom type verwendet, um Funktionen anzugeben, die nicht zurückkehren. Dazu gehören:

  • panic!()
  • Looping immer
  • Beenden des Programms (mit Ausnahme von main() zurückkehrt), wie exit(), deren Signatur pub fn exit(code: i32) -> !
+3

Meine Favoriten sind 'unimplemented!()' Und 'unreachable!()'. – Shepmaster

Verwandte Themen