2016-05-27 12:31:23 +03:00
|
|
|
|
---
|
2022-07-06 23:31:18 +03:00
|
|
|
|
language: Rust
|
2016-05-27 12:31:23 +03:00
|
|
|
|
contributors:
|
|
|
|
|
- ["P1start", "http://p1start.github.io/"]
|
|
|
|
|
translators:
|
|
|
|
|
- ["Christian Albrecht", "https://github.com/coastalchief"]
|
|
|
|
|
lang: de-de
|
|
|
|
|
filename: lernerust-de.rs
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
Rust ist eine Programmiersprache von Mozilla Research.
|
|
|
|
|
Rust vereint Sicherheit, Nebenläufigkeit und eine hohe Praxistauglichkeit.
|
|
|
|
|
|
|
|
|
|
Sicherheit bedeuted, dass Programmierfehler ausgeschlossen werden, die zu
|
|
|
|
|
Speicherzugriffsfehlern führen könnten. Das funktioniert u.a. dadurch, dass
|
|
|
|
|
es keinen Garbage Collector gibt, sondern ein besonderes Typsystem.
|
|
|
|
|
|
|
|
|
|
Das erste Release von Rust, 0.1, wurde im Januar 2012 veröffentlicht.
|
|
|
|
|
In den nächsten drei Jahren wurde die Sprache so schnell und aktiv weiter-
|
|
|
|
|
entwickelt, dass es einfach keine stabile gab und geraten wurde den
|
|
|
|
|
nightly build zu nutzen.
|
|
|
|
|
|
|
|
|
|
Am 15. Mai 2015 wurde Rust 1.0 freigegeben, und zwar mit der Garantie einer
|
|
|
|
|
Abwärtskompatabilität. Verbesserungen der Kompilierzeit und andere Compiler
|
|
|
|
|
verbesserungen finden im Moment im nightly build statt. Von Rust gibt es im
|
|
|
|
|
Moment ungefähr alle sechs Wochen ein Release. Rust 1.1 beta wurde zusammen
|
|
|
|
|
mit dem 1.0 Release zur Verfügung gestellt.
|
|
|
|
|
|
|
|
|
|
Obwohl Rust eine ziemlich low-level Sprache ist, vereint sie Ansätze aus
|
|
|
|
|
der Welt der funktionalen, der objektorientierten und der nebenläufigen
|
|
|
|
|
Programmierung. Dadurch kann in Rust nicht nur schnell, sondern auch sehr
|
|
|
|
|
effizient entwickelt werden.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
// Dies ist ein Kommentar. Ein einzeiliger...
|
|
|
|
|
/* ...und multi-zeilen Kommentare sehe so aus */
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// 0. Installation //
|
|
|
|
|
/////////////////////
|
|
|
|
|
// Stabile binaries gibt es unter https://www.rust-lang.org/downloads.html
|
|
|
|
|
|
|
|
|
|
// Programme werden in .rs Dateien geschrieben also zum Beispiel
|
|
|
|
|
// "main.rs" und dann kompiliert "rustc main.rs"
|
|
|
|
|
// Herauskommt eine ausführbare Datei "main"
|
|
|
|
|
// Für dieses Tutorial reicht das vollkommen aus. Für größere Projekte
|
|
|
|
|
// sollte das unten beschriebene Cargo angeschaut werden.
|
|
|
|
|
|
|
|
|
|
// Cargo
|
|
|
|
|
// Ein gängiges Tool um Rust Projekte zu verwalten ist Cargo. Es macht im
|
|
|
|
|
// wesentlichen drei Dinge: Code bauen, Dependencies laden und
|
|
|
|
|
// Dependencies bauen.
|
|
|
|
|
// Um ein vorhandenes Projekt zu cargo-ifyen müssen drei Dinge gemacht werden
|
|
|
|
|
// * Erstelle eine Cargo.toml Konfigurationsdatei
|
|
|
|
|
// * Verschiebe Source Code in ein src Verzeichnis
|
|
|
|
|
// * Lösche das alte Executable
|
|
|
|
|
//
|
|
|
|
|
// 'cargo build' baut den Code
|
|
|
|
|
// 'cargo run' baut und führt das Programm aus
|
|
|
|
|
|
|
|
|
|
///////////////
|
|
|
|
|
// 1. Basics //
|
|
|
|
|
///////////////
|
|
|
|
|
|
|
|
|
|
// Funktionen
|
|
|
|
|
// `i32` ist der Typ für einen 32-bit signed Integer
|
|
|
|
|
fn add2(x: i32, y: i32) -> i32 {
|
|
|
|
|
// Impliziter return (kein Semikolon)
|
|
|
|
|
x + y
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Main Funktion
|
|
|
|
|
fn main() {
|
|
|
|
|
// Zahlen //
|
|
|
|
|
|
|
|
|
|
// Unveränderliche Variable
|
|
|
|
|
let x: i32 = 1;
|
|
|
|
|
|
|
|
|
|
// Integer/float Suffixe
|
|
|
|
|
let y: i32 = 13i32;
|
|
|
|
|
let f: f64 = 1.3f64;
|
|
|
|
|
|
|
|
|
|
// Type inference
|
|
|
|
|
Meistens kann der Rust Compiler selbst schlussfolgern, von welchem
|
|
|
|
|
Typ eine Variable ist, so dass man den Typ nicht explizit angeben muss.
|
|
|
|
|
In diesem Tutorial werden Typen explizit angegeben, um zu demonstrieren,
|
|
|
|
|
welche Möglichkeiten es gibt. Wenn man damit vertraut ist, kann man die
|
|
|
|
|
Typen auch weglassen und die Type Inference hilft dann im Hintergrund.
|
|
|
|
|
|
|
|
|
|
let implicit_x = 1;
|
|
|
|
|
let implicit_f = 1.3;
|
|
|
|
|
|
|
|
|
|
// Arithmetik
|
|
|
|
|
let sum = x + y + 13;
|
|
|
|
|
|
|
|
|
|
// Veränderliche Variable
|
|
|
|
|
let mut mutable = 1;
|
|
|
|
|
mutable = 4;
|
|
|
|
|
mutable += 2;
|
|
|
|
|
|
|
|
|
|
// Strings //
|
|
|
|
|
// Strings gibt es in zwei Typen: &str und String
|
|
|
|
|
|
|
|
|
|
// Zunächst &str
|
|
|
|
|
let x: &str = "hello world!";
|
|
|
|
|
|
|
|
|
|
// Ausgabe
|
|
|
|
|
println!("{} {}", f, x); // 1.3 hello world
|
|
|
|
|
|
|
|
|
|
// Ein `String` – heap-allokierter String
|
|
|
|
|
let s: String = "hello world".to_string();
|
|
|
|
|
|
|
|
|
|
// Ein string slice – ist eigentlich ein unveränderlicher Pointer
|
|
|
|
|
// auf einen String – er enthält nicht den Inhalt den String, sondern
|
|
|
|
|
// eben nur den Pointer auf etwas, dass den Inhalt kennt:
|
|
|
|
|
// (In diesem Fall, `s`)
|
|
|
|
|
let s_slice: &str = &s;
|
|
|
|
|
|
|
|
|
|
// Ausgabe
|
|
|
|
|
println!("{} {}", s, s_slice); // hello world hello world
|
|
|
|
|
|
|
|
|
|
// Vektoren/Arrays //
|
|
|
|
|
|
|
|
|
|
// Ein Array mit fester Größe
|
|
|
|
|
let vier_ints: [i32; 4] = [1, 2, 3, 4];
|
|
|
|
|
|
|
|
|
|
// Ein dynamisches Array (Vektorentor)
|
|
|
|
|
let mut vector: Vec<i32> = vec![1, 2, 3, 4];
|
|
|
|
|
vector.push(5);
|
|
|
|
|
|
|
|
|
|
// Ein slice – eine unveränderliche Ansicht, oder Pointer auf einen
|
|
|
|
|
// Vektor oder ein Array. Wie bei Strings, nur eben bei Vektoren
|
|
|
|
|
let slice: &[i32] = &vector;
|
|
|
|
|
|
|
|
|
|
// Benutze `{:?}` um eine debug Ausgabe zu erzeugen
|
|
|
|
|
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
|
|
|
|
|
|
|
|
|
|
// Tuples //
|
|
|
|
|
|
|
|
|
|
// Ein Tuple ist eine Liste mit fester Größe und kann Werte
|
|
|
|
|
// von unterschiedlichen Typen enthalten
|
|
|
|
|
let x: (i32, &str, f64) = (1, "hello", 3.4);
|
|
|
|
|
|
|
|
|
|
// Werte aus Vektor mit `let` destrukturieren
|
|
|
|
|
let (a, b, c) = x;
|
|
|
|
|
println!("{} {} {}", a, b, c); // 1 hello 3.4
|
|
|
|
|
|
|
|
|
|
// Vektor Indizes
|
|
|
|
|
println!("{}", x.1); // hello
|
|
|
|
|
|
|
|
|
|
//////////////
|
|
|
|
|
// 2. Typen //
|
|
|
|
|
//////////////
|
|
|
|
|
|
|
|
|
|
// Struct
|
|
|
|
|
struct Punkt {
|
|
|
|
|
x: i32,
|
|
|
|
|
y: i32,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let anfang: Punkt = Punkt { x: 0, y: 0 };
|
|
|
|
|
|
|
|
|
|
// Ein struct mit unbenannten Felder heisst ‘tuple struct’
|
|
|
|
|
struct Punkt2(i32, i32);
|
|
|
|
|
|
|
|
|
|
let anfang2 = Punkt2(0, 0);
|
|
|
|
|
|
|
|
|
|
// Einfache enum, so ähnlich wie in C
|
|
|
|
|
enum Richtung {
|
|
|
|
|
Links,
|
|
|
|
|
Rechts,
|
|
|
|
|
Hoch,
|
|
|
|
|
Runter,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let hoch = Richtung::Hoch;
|
|
|
|
|
|
|
|
|
|
// Enum mit Feldern
|
|
|
|
|
enum OptionalI32 {
|
|
|
|
|
EinI32(i32),
|
|
|
|
|
Nix,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let zwei: OptionalI32 = OptionalI32::EinI32(2);
|
|
|
|
|
let nix = OptionalI32::Nix;
|
|
|
|
|
|
|
|
|
|
// Generics //
|
|
|
|
|
|
|
|
|
|
struct Foo<T> { bar: T }
|
|
|
|
|
|
|
|
|
|
// In der Standard Bibliothek heisst das hier `Option`
|
|
|
|
|
enum Optional<T> {
|
|
|
|
|
EinWert(T),
|
|
|
|
|
KeinWert,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Methoden //
|
|
|
|
|
|
|
|
|
|
impl<T> Foo<T> {
|
|
|
|
|
// Methoden erwarten einen `self` Parameter
|
|
|
|
|
fn get_bar(self) -> T {
|
|
|
|
|
self.bar
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let a_foo = Foo { bar: 1 };
|
|
|
|
|
println!("{}", a_foo.get_bar()); // 1
|
|
|
|
|
|
|
|
|
|
// Traits (vergleichbar mit Interfaces oder Typklassen in anderen Sprachen)
|
|
|
|
|
// In Traits werden nur Method Signaturen erstellt.
|
|
|
|
|
// Die Implementierung findet im impl statt.
|
|
|
|
|
|
|
|
|
|
trait MacheIrgendwas<T> {
|
|
|
|
|
fn macheIrgendwas(self) -> Option<T>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> MacheIrgendwas<T> for Foo<T> {
|
|
|
|
|
fn macheIrgendwas(self) -> Option<T> {
|
|
|
|
|
mache(self.bar)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let anderes_foo = Foo { bar: 1 };
|
|
|
|
|
println!("{:?}", anderes_foo.macheIrgendwas()); // mache(1)
|
|
|
|
|
|
|
|
|
|
/////////////////////////
|
|
|
|
|
// 3. Pattern matching //
|
|
|
|
|
/////////////////////////
|
|
|
|
|
|
|
|
|
|
let foo = OptionalI32::AnI32(1);
|
|
|
|
|
match foo {
|
|
|
|
|
OptionalI32::EinI32(n) => println!("hier ist ein i32: {}", n),
|
|
|
|
|
OptionalI32::Nix => println!("hier ist nix!"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Advanced pattern matching
|
|
|
|
|
struct FooBar { x: i32, y: OptionalI32 }
|
|
|
|
|
let bar = FooBar { x: 15, y: OptionalI32::EinI32(32) };
|
|
|
|
|
|
|
|
|
|
match bar {
|
|
|
|
|
FooBar { x: 0, y: OptionalI32::EinI32(0) } =>
|
|
|
|
|
println!("Beide Zahlen sind 0!"),
|
|
|
|
|
FooBar { x: n, y: OptionalI32::EinI32(m) } if n == m =>
|
|
|
|
|
println!("Beide Zahlen sind gleich"),
|
|
|
|
|
FooBar { x: n, y: OptionalI32::EinI32(m) } =>
|
|
|
|
|
println!("Zahlen sind unterschiedlich: {} {}", n, m),
|
|
|
|
|
FooBar { x: _, y: OptionalI32::Nix } =>
|
|
|
|
|
println!("Die zweite Zahl ist leer!"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// 4. Control //
|
|
|
|
|
/////////////////////
|
|
|
|
|
|
|
|
|
|
// `for` Schleife/Iterationen
|
|
|
|
|
let array = [1, 2, 3];
|
2021-11-02 00:27:42 +03:00
|
|
|
|
for i in array {
|
2016-05-27 12:31:23 +03:00
|
|
|
|
println!("{}", i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ranges
|
|
|
|
|
for i in 0u32..10 {
|
|
|
|
|
print!("{} ", i);
|
|
|
|
|
}
|
|
|
|
|
println!("");
|
|
|
|
|
// gibt aus: `0 1 2 3 4 5 6 7 8 9 `
|
|
|
|
|
|
|
|
|
|
// `if`
|
|
|
|
|
if 1 == 1 {
|
|
|
|
|
println!("Mathe ist klappt!");
|
|
|
|
|
} else {
|
|
|
|
|
println!("Oh nein...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `if` als Ausdruck
|
|
|
|
|
let wert = if true {
|
|
|
|
|
"gut"
|
|
|
|
|
} else {
|
|
|
|
|
"schlecht"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// `while` Schleife
|
|
|
|
|
while 1 == 1 {
|
|
|
|
|
println!("Läuft...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unendliche Schleifen
|
|
|
|
|
loop {
|
|
|
|
|
println!("Hello!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
// 5. Speichersicherheit & Pointer //
|
|
|
|
|
/////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Owned pointer – nur eine Sache kann einen Pointer 'besitzen'.
|
|
|
|
|
// Das heisst, wenn das Objekt `Box` seinen scope verlässt oder verliert,
|
|
|
|
|
// wird es automatisch im Speicher de-allokiert.
|
|
|
|
|
let mut mine: Box<i32> = Box::new(3);
|
|
|
|
|
// Jetzt wird die Box dereferenziert
|
|
|
|
|
*mine = 5;
|
|
|
|
|
// Jetzt geht `mine` in den Besitz von `now_its_mine` über.
|
|
|
|
|
// `mine` wird verschoben.
|
|
|
|
|
let mut now_its_mine = mine;
|
|
|
|
|
*now_its_mine += 2;
|
|
|
|
|
|
|
|
|
|
println!("{}", now_its_mine); // ergibt 7
|
|
|
|
|
|
|
|
|
|
// Das würde nicht kompilieren, da `now_its_mine` jetzt den Pointer besitzt
|
|
|
|
|
// println!("{}", mine);
|
|
|
|
|
|
|
|
|
|
// Reference – ein unveränderlicher Pointer der fremde Daten referenziert
|
|
|
|
|
// Wenn eine Referenz auf einen Wert gesetzt wird, heisst das, dass man den
|
|
|
|
|
// Wert ausleiht (‘borrowed’).
|
|
|
|
|
// Ein ausgeliehener Wert ist unveränderlich und lebt solange wie der
|
|
|
|
|
// Scope existiert, in dem er erstellt wurde.
|
|
|
|
|
let mut var = 4;
|
|
|
|
|
var = 3;
|
|
|
|
|
let ref_var: &i32 = &var;
|
|
|
|
|
|
2016-09-27 17:42:40 +03:00
|
|
|
|
println!("{}", var); // Anders als `mine`, `var` kann hier weiter verwendet werden
|
2016-05-27 12:31:23 +03:00
|
|
|
|
println!("{}", *ref_var);
|
|
|
|
|
// var = 5; // das kompiliert nicht, da `var` ausgeliehen ist
|
|
|
|
|
// *ref_var = 6; // das kompiliert auch nicht, da `ref_var` eine unveränderliche Referenz ist
|
|
|
|
|
|
|
|
|
|
// Veränderliche Referenzen
|
|
|
|
|
// Solange ein Wert veränderlich geliehen wurde, kann man nicht darauf zugreifen
|
|
|
|
|
let mut var2 = 4;
|
|
|
|
|
let ref_var2: &mut i32 = &mut var2;
|
|
|
|
|
*ref_var2 += 2; // '*' wird benutzt um auf den veränderlich geliehenen Wert var2 zu zeigen
|
|
|
|
|
|
|
|
|
|
println!("{}", *ref_var2); // 6 , //var2 würde nicht kompilieren. //ref_var2 ist vom Typ &mut i32, also //stores a reference to an i32 not the value.
|
|
|
|
|
// var2 = 2; // würde das nicht kompilieren, da `var2` geliehen wurde.
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Weitere Informationen
|
|
|
|
|
|
|
|
|
|
Es gibt eine ganze Reihe mehr über Rust zu sagen. Dieser Text gibt nur einen
|
|
|
|
|
Einblick in die wichtigsten Sprachmerkmale.
|
|
|
|
|
Um mehr über Rust zu erfahren, sollte man mit den folgenden Stellen starten:
|
|
|
|
|
|
|
|
|
|
1. Englisch:
|
|
|
|
|
* [Die offizielle Rust Webseite](http://rust-lang.org)
|
|
|
|
|
* [The Rust Programming Language](https://doc.rust-lang.org/stable/book/README.html)
|
|
|
|
|
* [/r/rust](http://reddit.com/r/rust)
|
|
|
|
|
* the #rust channel on irc.mozilla.org
|
|
|
|
|
|
|
|
|
|
2. Deutsch
|
|
|
|
|
* [Rust Wikipedia](https://de.wikipedia.org/wiki/Rust_(Programmiersprache))
|
|
|
|
|
* [Artikel im LinuxMagazin](http://www.linux-magazin.de/Ausgaben/2015/08/Rust)
|