Zum Inhalt springen

Funktionen in Rust

Eine Funktion ist ein wiederverwendbarer Codeblock mit einem Namen. Statt dieselben Schritte immer wieder hinzuschreiben, packst du sie einmal in eine Funktion und rufst sie auf, wann immer du sie brauchst. Eine Funktion hast du sogar schon benutzt: main.

Du definierst eine Funktion mit fn. Du rufst sie auf, indem du ihren Namen gefolgt von () schreibst:

fn greet() {
println!("Hallo aus einer Funktion!");
}
fn main() {
greet(); // aufrufen
greet(); // noch einmal aufrufen
}

Ausgabe:

Hallo aus einer Funktion!
Hallo aus einer Funktion!
▶ Selbst ausprobieren

Richtig nützlich werden Funktionen, wenn du ihnen Daten zum Arbeiten übergibst. Diese Eingaben heißen Parameter. In Rust musst du für jeden Parameter den Typ angeben:

fn greet(name: &str) {
println!("Hallo, {name}!");
}
fn main() {
greet("Alice");
greet("Bob");
}

Ausgabe:

Hallo, Alice!
Hallo, Bob!
▶ Selbst ausprobieren

Du kannst so viele Parameter haben, wie du brauchst, getrennt durch Kommas:

fn describe(name: &str, age: u32) {
println!("{name} ist {age} Jahre alt");
}
fn main() {
describe("Ferris", 10);
}

Ausgabe:

Ferris ist 10 Jahre alt
▶ Selbst ausprobieren

Die übergebenen Werte werden den Parametern nach ihrer Position zugeordnet: Der erste Wert landet in name, der zweite in age. Übergibst du sie in der falschen Reihenfolge, etwa describe(10, "Ferris"), ist das ein Compilerfehler, weil die Typen nicht passen.

Eine Funktion kann dem Aufrufer einen Wert zurückgeben. Den Rückgabetyp gibst du nach einem Pfeil -> an:

fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let sum = add(3, 4);
println!("3 + 4 = {sum}");
}

Ausgabe:

3 + 4 = 7
▶ Selbst ausprobieren

Fällt dir auf, dass a + b im Beispiel oben kein Semikolon hat? Das ist eine zentrale Idee in Rust:

  • Ein Ausdruck ohne Semikolon ist der Wert, der zurückgegeben wird.
  • Ein Semikolon macht daraus eine Anweisung, die nichts zurückgibt.

Das hier funktioniert also nicht:

fn add(a: i32, b: i32) -> i32 {
a + b; // ❌ das Semikolon heißt „gib nichts zurück“ – versprochen war aber ein i32
}

Der Compiler beschwert sich, dass die Funktion ein i32 zurückgeben sollte, es aber nicht tut. Entferne einfach das Semikolon in der letzten Zeile.

fn square(n: i32) -> i32 {
n * n
}
fn main() {
let result = square(5);
println!("5 zum Quadrat ist {result}");
}

Ausgabe:

5 zum Quadrat ist 25
▶ Selbst ausprobieren

Schreib eine Funktion to_fahrenheit, die eine Temperatur in Celsius als f64 entgegennimmt und sie in Fahrenheit zurückgibt. Die Formel lautet c * 9.0 / 5.0 + 32.0. Ruf sie für 0, 100 und 37 Grad auf. Tipp: Die Signatur ist fn to_fahrenheit(c: f64) -> f64, und der Rumpf ist ein einziger Ausdruck ohne Semikolon.

Lösung anzeigen
fn to_fahrenheit(c: f64) -> f64 {
c * 9.0 / 5.0 + 32.0
}
fn main() {
println!("0°C sind {}°F", to_fahrenheit(0.0));
println!("100°C sind {}°F", to_fahrenheit(100.0));
println!("37°C sind {}°F", to_fahrenheit(37.0));
}

Ausgabe:

0°C sind 32°F
100°C sind 212°F
37°C sind 98.6°F
▶ Selbst ausprobieren

Achte darauf, dass wir 0.0 übergeben, nicht 0. Der Parameter ist ein f64, und Rust macht aus einer Ganzzahl nicht stillschweigend eine Gleitkommazahl. Hat ein f64 keine Nachkommastellen, gibt {} ihn ohne .0 aus – deshalb siehst du 32 und nicht 32.0.

Schreib eine Funktion largest(a: i32, b: i32, c: i32) -> i32, die die größte ihrer drei Zahlen zurückgibt. Teste sie mit (3, 9, 4) und (-2, -8, -5). Tipp: if ist in Rust ein Ausdruck (siehe If…Else). Eine if / else if / else-Kette kann also die letzte Zeile der Funktion sein.

Lösung anzeigen
fn largest(a: i32, b: i32, c: i32) -> i32 {
if a >= b && a >= c {
a
} else if b >= c {
b
} else {
c
}
}
fn main() {
println!("{}", largest(3, 9, 4));
println!("{}", largest(-2, -8, -5));
}

Ausgabe:

9
-2
▶ Selbst ausprobieren

Keiner der Zweige endet mit einem Semikolon. Jeder ist ein Ausdruck, die ganze if-Kette liefert einen davon zurück, und der wird zum Rückgabewert. Mit >= statt > bekommst du auch bei Gleichstand einen Wert.

  • Funktionen definierst du mit fn und rufst sie mit name() auf.
  • Parameter sind Eingaben; jeder braucht einen Typ: fn greet(name: &str).
  • Den Rückgabetyp gibst du mit -> Typ an.
  • Der letzte Ausdruck ohne Semikolon ist der Rückgabewert.
  • return wert; funktioniert auch, wird aber meist nur für ein vorzeitiges Zurückgeben verwendet.

Kurzer Check

1. Musst du in Rust den Typ jedes Funktionsparameters angeben?

2. Wie gibst du den Rückgabetyp einer Funktion an?

3. Warum wird a + b (ohne Semikolon) am Ende einer Funktion zum Rückgabewert?

4. Spielt es eine Rolle, ob du eine Funktion oberhalb oder unterhalb der Stelle definierst, an der du sie aufrufst (z. B. über oder unter main)?

Punkte: 0 / 4