Programmiersprachen Rust

Rust - der Unit Typ

In Rust ist der Unit-Typ (()) ein besonderer Typ, der in vielen Situationen verwendet wird, in denen kein spezifischer Wert benötigt wird.


3 Minuten Lesezeit
13 Okt 2024
documents/pexels-mushroom-4485456_2dfA35h.jpg

Was lerne ich in diesem Kurs?

In diesem Tutorial wird erklärt, was der Unit-Typ ist, wann er verwendet wird und wie er in verschiedenen Kontexten in Rust auftaucht.

Er repräsentiert das Konzept "kein Wert" oder "leere Rückgabe" und ist der Standardrückgabetyp für Funktionen, die nichts zurückgeben. Der Unit-Typ wird oft mit dem in vielen anderen Programmiersprachen verwendeten void-Typ verglichen, hat aber in Rust einige Besonderheiten.

1. Was ist der Unit-Typ ()?

Der Unit-Typ () ist ein Datentyp, der genau einen Wert hat: (). Dieser Wert und Typ repräsentieren eine leere Menge von Informationen und werden verwendet, wenn kein tatsächlicher Wert benötigt wird. Anders als in einigen anderen Programmiersprachen, in denen eine spezielle Rückgabe wie void existiert, verwendet Rust den Unit-Typ für ähnliche Situationen.

Beispiel: Der Unit-Typ ()

fn main() {
    let x: () = ();
    println!("Der Wert von x ist: {:?}", x);
}

Ausgabe:

Der Wert von x ist: ()

In diesem Beispiel wird ein Wert des Typs () erstellt und ausgegeben. Da es nur einen möglichen Wert für den Unit-Typ gibt, ist der Ausdruck () immer gleich ().

2. Verwendung des Unit-Typs in Funktionen

In Rust haben alle Funktionen einen Rückgabetyp. Wenn eine Funktion nichts zurückgibt, gibt sie stattdessen den Unit-Typ () zurück. Rust fügt automatisch () als Rückgabewert hinzu, wenn kein anderer Rückgabetyp explizit angegeben wird.

Beispiel: Eine Funktion ohne Rückgabewert

fn keine_rueckgabe() {
    println!("Diese Funktion gibt nichts zurück.");
}

fn main() {
    let result = keine_rueckgabe(); // result hat den Typ `()`
    println!("Rückgabewert: {:?}", result);
}

Ausgabe:

Diese Funktion gibt nichts zurück.
Rückgabewert: ()

In diesem Beispiel gibt die Funktion keine_rueckgabe explizit nichts zurück, aber Rust setzt automatisch den Unit-Typ () als Rückgabewert. Dadurch hat die Variable result den Typ ().

Funktionen mit explizitem Unit-Typ als Rückgabewert

Man kann den Unit-Typ auch explizit als Rückgabewert angeben, aber das ist in der Regel nicht notwendig, da Rust dies automatisch handhabt.

fn explizit_unit() -> () {
    println!("Diese Funktion gibt explizit den Unit-Typ zurück.");
}

fn main() {
    explizit_unit();
}

Diese Funktion gibt ebenfalls den Unit-Typ () zurück, obwohl er explizit im Funktionskopf angegeben wird. Dies ist gleichbedeutend mit einer Funktion, die keine Rückgabe spezifiziert.

3. Der Unit-Typ in Ausdrücken

Der Unit-Typ taucht häufig in Rust-Ausdrücken auf, insbesondere in Blöcken oder Kontrollstrukturen, bei denen keine Berechnung durchgeführt wird, die einen tatsächlichen Wert ergibt.

Beispiel: Unit-Typ in if-Blöcken ohne Wert

fn main() {
    let condition = true;

    let result = if condition {
        println!("Bedingung ist wahr");
    } else {
        println!("Bedingung ist falsch");
    };

    println!("Rückgabewert des if-Blocks: {:?}", result);
}

Ausgabe:

Bedingung ist wahr
Rückgabewert des if-Blocks: ()

In diesem Beispiel gibt der if-Block den Unit-Typ () zurück, da innerhalb der if- und else-Blöcke nur der println!-Makro aufgerufen wird, der ebenfalls () zurückgibt.

Beispiel: Der Unit-Typ in Schleifen

In Rust-Schleifen, die normalerweise nicht zurückkehren (wie loop oder for), wird ebenfalls der Unit-Typ zurückgegeben, es sei denn, die Schleife wird explizit mit einem Wert unterbrochen.

fn main() {
    let x = for i in 0..5 {
        println!("Zähler: {}", i);
    };

    println!("Der Wert von x ist: {:?}", x);
}

Ausgabe:

Zähler: 0
Zähler: 1
Zähler: 2
Zähler: 3
Zähler: 4
Der Wert von x ist: ()

In diesem Fall gibt die Schleife nichts zurück und der Wert von x ist ().

4. Der Unit-Typ als Rückgabewert bei Fehlern

Rust verwendet den Unit-Typ auch häufig in Funktionen oder Strukturen, die eine Art von Fehler darstellen können, aber keinen expliziten Fehlerwert zurückgeben. Ein gutes Beispiel dafür ist die Funktion std::result::Result<T, E>, bei der T der Typ des Erfolgswertes und E der Fehlerwert ist. In manchen Fällen kann E den Unit-Typ () annehmen, um zu signalisieren, dass der Fehler nicht näher spezifiziert wird.

Beispiel: Result mit Unit-Typ als Fehler

fn operation_mit_fehler() -> Result<i32, ()> {
    // Ein Fehler tritt auf
    Err(())
}

fn main() {
    match operation_mit_fehler() {
        Ok(value) => println!("Erfolgreicher Wert: {}", value),
        Err(_) => println!("Ein Fehler ist aufgetreten"),
    }
}

Ausgabe:

Ein Fehler ist aufgetreten

In diesem Beispiel wird Err(()) verwendet, um anzuzeigen, dass ein Fehler aufgetreten ist, aber es gibt keine detaillierten Informationen über den Fehler. Dies ist nützlich, wenn nur zwischen Erfolg und Misserfolg unterschieden werden muss, ohne spezifische Fehlerbehandlung.

5. Unterschiede zu void in anderen Sprachen

Der Unit-Typ () in Rust ähnelt dem void-Typ in Sprachen wie C oder C++. Es gibt jedoch wichtige Unterschiede:

  • In Rust ist () ein tatsächlicher Typ mit einem Wert, während void in anderen Sprachen keinen Wert hat.
  • Der Unit-Typ kann wie jeder andere Wert in Rust verwendet werden, etwa als Rückgabewert von Funktionen, in Ausdrücken oder als Platzhalter.