In Rust bezeichnet man das Zuweisen eines Werts zu einem Namen als Binding. Bindings sind unveränderlich, es sei denn, sie werden mit dem Schlüsselwort mut deklariert. Da Rust eine statisch typisierte Sprache ist, hat jedes Binding einen Typ, der zur Kompilierzeit bekannt ist.
Bindings werden am häufigsten mit dem Schlüsselwort let definiert. Bei den meisten Bindings ist die Angabe eines Typs optional, da Rusts Typinferenz den Typ normalerweise anhand des Werts ableiten kann. Ein Binding sieht so aus:
// Automatically inferred type
let fingers = 10;
Funktionen sind Items. Während Bindings typischerweise auf einen bestimmten Wert verweisen, beziehen sich Items auf eine Einheit der Codeorganisation, typischerweise eine Funktion oder ein Modul, die während der gesamten Lebensdauer des Programms verfügbar ist. Eine Funktion gibt automatisch das Ergebnis ihres letzten Ausdrucks zurück. Eine Funktion kann 0 oder mehr Parameter haben, also Bindings, deren Lebensdauer auf den Funktionsaufruf beschränkt ist.
Typinferenz ist für Funktionen theoretisch möglich, wurde aber als bewusste Designentscheidung der Sprache deaktiviert. Das bedeutet, dass du beim Schreiben von Code etwas mehr Zeit aufwenden musst, um genau anzugeben, welche Eingabe- und Ausgabetypen eine Funktion hat. Beim Lesen des Codes sparst du dafür Zeit, weil alle Ein- und Ausgabetypen explizit festgelegt sind.
fn add(x: i32, y: i32) -> i32 {
x + y
}
Eine Funktion rufst du auf, indem du ihren Namen gefolgt von zwei runden Klammern angibst. Wenn die Funktion Parameter benötigt, musst du für jeden ein Argument in den Klammern angeben.
let five = add(2, 3);
Wenn der Typ eines Bindings nicht abgeleitet werden kann, meldet der Compiler einen Fehler. Um das zu beheben, füge dem Binding eine explizite Typannotation hinzu.
// Explicit type annotation
let fingers: i32 = 10;
Items können in Rust vor oder nach ihrer Definition verwendet werden, weil sie eine statische Lebensdauer haben. Bindings hingegen können erst nach ihrer Definition verwendet werden. Wenn du ein Binding vor seiner Definition verwendest, führt das zu einem Kompilierfehler.
fn main() {
// `fn add` hasn't yet been defined, but that's perfectly ok
dbg!(add(3, 4));
}
fn add(x: i32, y: i32) -> i32 {
x + y
}
// this won't compile; `a` is used before its binding is defined
let b = a;
let a = x + y;
Rust verwendet geschweifte Klammern ({}), um einen Gültigkeitsbereich zu definieren. Ein Binding, das innerhalb eines Gültigkeitsbereichs definiert wird, kann nicht daraus entkommen.
let a = 1;
dbg!(a); // 1
{
// Here, we re-bind `a` to a new value, which is still immutable.
// This technique is called _shadowing_. The new binding is constrained to
// this anonymous scope. Outside this scope, the previous binding still
// applies.
let a = 2;
let b = 3;
dbg!(a, b); // 2, 3
}
// can't use `b` anymore because it is out of scope
// dbg!(b);
// The shadowed `a` in the inner scope above has fallen out of scope,
// leaving us with our original binding.
dbg!(a); // 1
Items werden in Rust oft in Modulen organisiert. Jede Crate ist implizit ein Modul, kann aber innere Untermodule beliebiger Tiefe definieren. Ein Modul gruppiert zusammengehörige Funktionalität und wird mit dem Schlüsselwort mod definiert.
mod calc_i32 {
fn add(a: i32, b: i32) -> i32 { a + b }
fn sub(a: i32, b: i32) -> i32 { a - b }
fn mul(a: i32, b: i32) -> i32 { a * b }
fn div(a: i32, b: i32) -> i32 { a / b }
}
Rust unterstützt zwei Arten von Kommentaren. Das Zeichen // kennzeichnet einen einzeiligen Kommentar; alles, was nach dem Zeichen bis zum Zeilenende folgt, wird ignoriert. Die Zeichen /* und */ kennzeichnen einen mehrzeiligen Kommentar; alles zwischen diesen beiden Zeichen wird ignoriert. Es ist idiomatisch und gute Praxis, einzeilige Kommentare zu bevorzugen.
Rust unterstützt außerdem Doc-Kommentare, die in der von cargo doc erzeugten Dokumentation erscheinen. Äußere Doc-Kommentare werden mit dem Zeichen /// gebildet, das sich genauso verhält wie das Zeichen //. Sie gelten für das Item, das auf sie folgt, zum Beispiel eine Funktion:
/// The `add` function produces the sum of its arguments.
fn add(x: i32, y: i32) -> i32 { x + y }
Innere Doc-Kommentare werden mit dem Zeichen //! gebildet, das sich genauso verhält wie das Zeichen //. Sie gelten für das Item, das sie umschließt, zum Beispiel ein Modul:
mod my_cool_module {
//! This module is the bee's knees.
}
Doc-Kommentare können beliebig lang sein und Markdown enthalten, das in die erzeugte Dokumentation gerendert wird.
In dieser Übung schreibst du etwas Code, der dir hilft, eine großartige Lasagne nach deinem Lieblingskochbuch zu kochen.
Du hast vier Aufgaben, die sich alle um die Zeit drehen, die du für das Kochen der Lasagne aufwendest.
Definiere das Binding expected_minutes_in_oven, um zu prüfen, wie viele Minuten die Lasagne im Ofen bleiben sollte. Laut dem Kochbuch beträgt die erwartete Ofenzeit 40 Minuten:
expected_minutes_in_oven()
// Returns: 40
Definiere die Funktion remaining_minutes_in_oven, die die tatsächlichen Minuten, die die Lasagne schon im Ofen war, als Parameter entgegennimmt und zurückgibt, wie viele Minuten die Lasagne noch im Ofen bleiben muss. Grundlage dafür ist die erwartete Ofenzeit in Minuten aus der vorherigen Aufgabe.
remaining_minutes_in_oven(30)
// Returns: 10
Definiere die Funktion preparation_time_in_minutes, die die Anzahl der Schichten, die du der Lasagne hinzugefügt hast, als Parameter entgegennimmt und zurückgibt, wie viele Minuten du für die Vorbereitung der Lasagne gebraucht hast. Dabei gehst du davon aus, dass jede Schicht 2 Minuten Vorbereitung braucht.
preparation_time_in_minutes(2)
// Returns: 4
Definiere die Funktion elapsed_time_in_minutes, die zwei Parameter entgegennimmt: Der erste Parameter ist die Anzahl der Schichten, die du der Lasagne hinzugefügt hast, und der zweite Parameter ist die Anzahl der Minuten, die die Lasagne schon im Ofen war. Die Funktion soll zurückgeben, wie viele Minuten du am Kochen der Lasagne gearbeitet hast. Das ist die Summe aus der Vorbereitungszeit in Minuten und der Zeit in Minuten, die die Lasagne bis jetzt im Ofen verbracht hat.
elapsed_time_in_minutes(3, 20)
// Returns: 26
Melde dich bei Exercism an, um Rust mit 99 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.