Rust -> rust && .notCompiling

This commit is contained in:
Daniel Kluge 2022-08-10 17:04:53 +02:00
parent 025f075209
commit 6e9b01aa28
8 changed files with 52 additions and 52 deletions

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-06-14T12:26:06.567Z :docdatetime: 2022-08-10T17:04:53+02:00
= Hello world = Hello world
@ -12,7 +12,7 @@ spezielle Art Funktion?), die einfach auf stdout printed.
~*In[2]:*~ ~*In[2]:*~
[source, Rust] [source, rust]
---- ----
println!("Hello world!"); println!("Hello world!");
---- ----
@ -31,7 +31,7 @@ Ein komplettes Programm zum Kompilieren hätte also den folgenden Inhalt:
~*In[3]:*~ ~*In[3]:*~
[source, Rust] [source, rust]
---- ----
fn main() { fn main() {
println!("Hello world!"); println!("Hello world!");

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-06-14T12:26:06.567Z :docdatetime: 2022-08-10T17:04:53+02:00
= Cargo = Cargo

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-06-14T12:27:14.473Z :docdatetime: 2022-08-10T17:04:53+02:00
= Erstes Spiel = Erstes Spiel
@ -13,7 +13,7 @@ Das Projekt wird wie in Notebook 01 beschrieben erstellt.
~*In[2]:*~ ~*In[2]:*~
[source, Rust] [source, rust]
---- ----
:dep evcxr_input :dep evcxr_input
// Das ^ ist für Jupyter // Das ^ ist für Jupyter
@ -83,7 +83,7 @@ Die crate `rand` kann jetzt im Code verwendet werden.
~*In[3]:*~ ~*In[3]:*~
[source, Rust] [source, rust]
---- ----
:dep rand = "0.3.15" :dep rand = "0.3.15"
// Das ^ ist von Jupyter // Das ^ ist von Jupyter
@ -109,7 +109,7 @@ Ein Fehler?
~*In[4]:*~ ~*In[4]:*~
[source, Rust] [source.notCompiling, rust]
---- ----
use std::cmp::Ordering; use std::cmp::Ordering;
@ -138,7 +138,7 @@ Wir müssen unser guess also umwandeln:
~*In[5]:*~ ~*In[5]:*~
[source, Rust] [source, rust]
---- ----
let guess: u32 = guess.trim().parse().expect("Please type a number!"); let guess: u32 = guess.trim().parse().expect("Please type a number!");
---- ----
@ -154,7 +154,7 @@ Jetzt sollte das Vergleichen auch klappen!
~*In[6]:*~ ~*In[6]:*~
[source, Rust] [source, rust]
---- ----
use std::cmp::Ordering; use std::cmp::Ordering;
@ -178,7 +178,7 @@ Damit wir mehrmals raten können, brauchen wir eine Schleife.
~*In[7]:*~ ~*In[7]:*~
[source, Rust] [source, rust]
---- ----
let secret_number: u32 = rand::thread_rng().gen_range(1, 101); let secret_number: u32 = rand::thread_rng().gen_range(1, 101);
loop { loop {
@ -226,7 +226,7 @@ Offensichtlich müssen wir die Schleife dann abbrechen.
~*In[8]:*~ ~*In[8]:*~
[source, Rust] [source, rust]
---- ----
let secret_number: u32 = rand::thread_rng().gen_range(1, 101); let secret_number: u32 = rand::thread_rng().gen_range(1, 101);
loop { loop {
@ -277,7 +277,7 @@ Zahl eingibt. Das können wir auch relativ einfach fixen:
~*In[9]:*~ ~*In[9]:*~
[source, Rust] [source, rust]
---- ----
loop { loop {
let mut guess = evcxr_input::get_string("Number? "); let mut guess = evcxr_input::get_string("Number? ");

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-07-05T17:57:48+02:00 :docdatetime: 2022-08-10T17:04:53+02:00
= Konzepte = Konzepte
@ -14,7 +14,7 @@ In anderen Sprachen ist das häufig `const` - in Rust gibt es aber auch `const`!
Das Folgende funktioniert also nicht: Das Folgende funktioniert also nicht:
[source, Rust] [source.notCompiling, Rust]
---- ----
fn main() { fn main() {
let x = "Hello world!"; let x = "Hello world!";
@ -25,7 +25,7 @@ fn main() {
Damit Variablen mutable sind, muss `mut` genutzt werden: Damit Variablen mutable sind, muss `mut` genutzt werden:
[source, Rust] [source, rust]
---- ----
fn main() { fn main() {
let mut x = "Hello world!"; let mut x = "Hello world!";
@ -46,7 +46,7 @@ Die Konvention für Konstanten ist snake case all caps.
Ein Beispiel dafür ist folgendes: Ein Beispiel dafür ist folgendes:
[source, Rust] [source, rust]
---- ----
const MINUTES_IN_A_DAY: u32 = 24 * 60; const MINUTES_IN_A_DAY: u32 = 24 * 60;
---- ----
@ -59,7 +59,7 @@ Anfangs habe ich es falsch verstanden: Ich dachte Shadowing wäre, dass eine Var
Allerdings ist es mehr ein "Reuse" eines alten Namens. Allerdings ist es mehr ein "Reuse" eines alten Namens.
Ein Beispiel: Ein Beispiel:
[source, Rust] [source, rust]
---- ----
fn main() { fn main() {
let x = 5; let x = 5;
@ -86,7 +86,7 @@ Wenn das nicht geht, muss manuell ein Typ festgelegt werden.
Ein Beispiel: Ein Beispiel:
[source, Rust] [source, rust]
---- ----
let guess: u32 = "42".parse().expect("Not a number!"); let guess: u32 = "42".parse().expect("Not a number!");
---- ----
@ -119,7 +119,7 @@ Interessant ist, dass es zusätzliche Methoden für alles gibt (nicht nur `add`)
- `overflowing_add` gibt einen Boolean, ob ein Overflow auftritt - `overflowing_add` gibt einen Boolean, ob ein Overflow auftritt
- `saturating_add` bleibt beim Maximum oder Minimum des verfügbaren Bereiches - `saturating_add` bleibt beim Maximum oder Minimum des verfügbaren Bereiches
[source, Rust] [source, rust]
---- ----
let number: u8 = 254; let number: u8 = 254;
println!("{}", number.wrapping_add(2)); println!("{}", number.wrapping_add(2));
@ -151,7 +151,7 @@ Sie sind aber schreibbar, wenn `mut` zur Initialisierung genutzt wird, also nich
Ein paar Beispiele als Code: Ein paar Beispiele als Code:
[source, Rust] [source, rust]
---- ----
let x: (f32, char, u8) = (1.0, '🐧', 3); let x: (f32, char, u8) = (1.0, '🐧', 3);
//_x.0 = 2.0; // geht nicht, da x nicht mut ist. //_x.0 = 2.0; // geht nicht, da x nicht mut ist.
@ -178,7 +178,7 @@ Für "Arrays" mit veränderbarer Länge gibt es Vektoren.
Wieder etwas Code: Wieder etwas Code:
[source, Rust] [source, rust]
---- ----
let x: [i32; 5] = [1, 2, 3, 4, 5]; let x: [i32; 5] = [1, 2, 3, 4, 5];
// ^ so sieht der Datentyp aus // ^ so sieht der Datentyp aus
@ -198,7 +198,7 @@ Sind wie normale Funktionen in C auch. Keyword ist `fn`.
Beispiel: Beispiel:
[source, Rust] [source, rust]
---- ----
fn calculate_sum(a: i32, b: i32) -> i64 { fn calculate_sum(a: i32, b: i32) -> i64 {
// Statements können natürlich normal genutzt werden // Statements können natürlich normal genutzt werden
@ -233,7 +233,7 @@ Es gibt auch noch spezielle Docstrings, aber das kommt später.
Beispiel für labels: Beispiel für labels:
[source, Rust] [source, rust]
---- ----
fn main() { fn main() {
'outer: loop { 'outer: loop {
@ -253,7 +253,7 @@ fn main() {
`break` mit Wert ist Rückgabe. `break` mit Wert ist Rückgabe.
Einfaches Beispiel: Einfaches Beispiel:
[source, Rust] [source, rust]
---- ----
fn main() { fn main() {
let mut counter = 0; let mut counter = 0;
@ -279,7 +279,7 @@ fn main() {
Looped durch eine Collection (wie in Python). Looped durch eine Collection (wie in Python).
[source, Rust] [source, rust]
---- ----
fn main() { fn main() {
let a = [10, 20, 30, 40, 50]; let a = [10, 20, 30, 40, 50];

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-07-05T15:32:40+02:00 :docdatetime: 2022-08-10T17:04:53+02:00
= Ownership = Ownership
@ -35,7 +35,7 @@ Dieser String-Typ hat den Vorteil, dass er eine dynamische Länge hat und damit
Ein Beispiel: Ein Beispiel:
[source, Rust] [source, rust]
---- ----
let mut x = String::from("Hello"); // Legt "dynamischen" String an let mut x = String::from("Hello"); // Legt "dynamischen" String an
x.push_str(" world!"); // Konkatiniert an den String x.push_str(" world!"); // Konkatiniert an den String
@ -48,7 +48,7 @@ Theoretisch kann `x` natürlich dann überschrieben werden, mit einem String and
=== Move === Move
[source, Rust] [source, rust]
---- ----
let x = 5; // Int -> feste Größe und auf Stack let x = 5; // Int -> feste Größe und auf Stack
let y = x; let y = x;
@ -110,7 +110,7 @@ Damit werden (unter anderem) Race Conditions schon beim Compilen verhindert.
=== Dangling references === Dangling references
[source, Rust] [source.notCompiling, rust]
---- ----
fn dangle() -> &String { fn dangle() -> &String {
let s = String::from("hello"); let s = String::from("hello");
@ -133,7 +133,7 @@ Nur so kann multithreading etc. funktionieren.
Dafür hat Rust den Slice-Datentyp. Dafür hat Rust den Slice-Datentyp.
Der funktioniert ähnlich wie Array-Ranges in Python. Der funktioniert ähnlich wie Array-Ranges in Python.
[source, Rust] [source, rust]
---- ----
let s = String::from("hello world"); let s = String::from("hello world");

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-07-05T17:45:24+02:00 :docdatetime: 2022-08-10T17:04:53+02:00
= Structs = Structs
@ -17,7 +17,7 @@ Man kann damit neue Datentypen machen.
=== "Normale" Structs === "Normale" Structs
[source, Rust] [source, rust]
---- ----
struct User { struct User {
active: bool, active: bool,
@ -47,7 +47,7 @@ Wenn die Variable heißt wie das Feld, kann man auch statt `email: email` einfac
Wenn man ein neues Struct aus einem alten mit Updates erstellen will, geht das auch mit einer Art Spread-Parameter: Wenn man ein neues Struct aus einem alten mit Updates erstellen will, geht das auch mit einer Art Spread-Parameter:
[source, Rust] [source, rust]
---- ----
let user2 = User { let user2 = User {
email: String::from("another@example.com"), email: String::from("another@example.com"),
@ -62,7 +62,7 @@ Hätten wir jetzt auch noch einen neuen `username` gesetzt (auch ein String) und
=== Tupel Structs === Tupel Structs
[source, Rust] [source, rust]
---- ----
struct RGBColor(u8, u8, u8); struct RGBColor(u8, u8, u8);
@ -75,7 +75,7 @@ Sind nutzbar wie Tupel (destrucuture und `.index` zum Zugriff auf Werte), allerd
=== Unit-Like Structs === Unit-Like Structs
[source, Rust] [source, rust]
---- ----
struct AlwaysEqual; struct AlwaysEqual;
---- ----
@ -119,7 +119,7 @@ Tatsächlich ist der sehr einfach und sehr OOPig.
Die folgenden Beispiele sollten relativ viel erklären: Die folgenden Beispiele sollten relativ viel erklären:
[source, Rust] [source, rust]
---- ----
struct Rectangle { struct Rectangle {
width: u32, width: u32,
@ -184,7 +184,7 @@ fn main() {
Eine Methode kann auch `&mut self` als ersten Parameter haben. Eine Methode kann auch `&mut self` als ersten Parameter haben.
Dann können auch Felder geschrieben werden. In diesem Fall werden Referenzen aber invalidiert! Dann können auch Felder geschrieben werden. In diesem Fall werden Referenzen aber invalidiert!
[source, Rust] [source, rust]
---- ----
struct Rectangle { struct Rectangle {
width: u32, width: u32,

View File

@ -1,5 +1,5 @@
:experimental: :experimental:
:docdatetime: 2022-07-25T20:00:23+02:00 :docdatetime: 2022-08-10T17:04:53+02:00
= Enums und Pattern Matching = Enums und Pattern Matching
@ -14,7 +14,7 @@ Grundsätzlich ist ein "Enum" in Rust näher am "Union" würde ich denken.
Ein einfaches Beispiel für ist der Typ `Option<T>` (vergleichbar mit Python oder Java `Optional`). Ein einfaches Beispiel für ist der Typ `Option<T>` (vergleichbar mit Python oder Java `Optional`).
Dieser ist entweder `None` oder `Some(value: T)` - es kann also ein Wert zusätzlich zur "Definition" beinhalten. Dieser ist entweder `None` oder `Some(value: T)` - es kann also ein Wert zusätzlich zur "Definition" beinhalten.
[source, Rust] [source, rust]
---- ----
enum Farbcode { enum Farbcode {
Hex, Hex,
@ -30,7 +30,7 @@ Die Funktion kann dann je nach Typ verschieden funktionieren.
Wie schon erwähnt, kann so ein Enum-Wert auch Werte beinhalten, um das zu machen, schreiben wir den Code einfach um: Wie schon erwähnt, kann so ein Enum-Wert auch Werte beinhalten, um das zu machen, schreiben wir den Code einfach um:
[source, Rust] [source, rust]
---- ----
enum Farbcode { enum Farbcode {
Hex(String), Hex(String),
@ -54,7 +54,7 @@ Natürlich können die Structs jeder Art sein.
Enums sind aber auch selber eine Art Struct. Enums sind aber auch selber eine Art Struct.
Also können wir für Enums auch Methoden definieren wie für Structs. Also können wir für Enums auch Methoden definieren wie für Structs.
[source, Rust] [source, rust]
---- ----
impl Farbcode { impl Farbcode {
fn to_css_string(&self) { fn to_css_string(&self) {
@ -84,7 +84,7 @@ So wie Rust bis jetzt klang, kann wahrscheinlich jedem Datentypen ein "match-Tra
Aber ganz einfach: Angenommen wir wollen die Methode `to_css_string` von oben implementieren. Aber ganz einfach: Angenommen wir wollen die Methode `to_css_string` von oben implementieren.
Diese Methode muss ja, je nach Typ, völlig unterschiedlich funktionieren. Diese Methode muss ja, je nach Typ, völlig unterschiedlich funktionieren.
[source, Rust] [source, rust]
---- ----
enum Farbcode { enum Farbcode {
Hex(String), Hex(String),
@ -126,7 +126,7 @@ Der Unterschied ist, dass bei `other` noch der Inhalt genutzt werden kann, bei `
Dieses if-Konstrukt nutzt man am besten, wenn man nur auf eine einzelne Variante eines Enums prüfen möchte. Dieses if-Konstrukt nutzt man am besten, wenn man nur auf eine einzelne Variante eines Enums prüfen möchte.
Letzendlich ist es ganz simpel: Letzendlich ist es ganz simpel:
[source, Rust] [source, rust]
---- ----
#[derive(Debug)] #[derive(Debug)]
enum Muenzwurf { enum Muenzwurf {

View File

@ -50,7 +50,7 @@ Im Hauptprogramm kann mit `mod modulname;` das Modul eingebunden werden. Gesucht
Zusätzlich kann auch direkt inline ein Modul erstellt werden. Zusätzlich kann auch direkt inline ein Modul erstellt werden.
Ein Beispiel: Ein Beispiel:
[source.notCompiling, Rust] [source.notCompiling, rust]
---- ----
mod testmodul { mod testmodul {
mod nested_modul { mod nested_modul {
@ -77,7 +77,7 @@ Das funktioniert noch *nicht*.
Denn standardmäßig ist alles private, was nicht explizit public ist. Denn standardmäßig ist alles private, was nicht explizit public ist.
Damit wir den obigen Aufruf machen können, muss der Code so aussehen: Damit wir den obigen Aufruf machen können, muss der Code so aussehen:
[source, Rust] [source, rust]
---- ----
mod testmodul { mod testmodul {
pub mod nested_modul { pub mod nested_modul {
@ -114,7 +114,7 @@ In Modulen können natürlich auch Structs und Enums verwendet werden.
Bei Structs ist die Besonderheit, dass die einzelnen Attribute auch wieder private oder public sein können. Bei Structs ist die Besonderheit, dass die einzelnen Attribute auch wieder private oder public sein können.
So kann man folgendes machen: So kann man folgendes machen:
[source, Rust] [source, rust]
---- ----
mod testmodul { mod testmodul {
pub struct Teststruct { pub struct Teststruct {