Rust -> rust && .notCompiling
This commit is contained in:
parent
025f075209
commit
6e9b01aa28
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-06-14T12:26:06.567Z
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= Hello world
|
||||
|
||||
@ -12,7 +12,7 @@ spezielle Art Funktion?), die einfach auf stdout printed.
|
||||
|
||||
|
||||
~*In[2]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
println!("Hello world!");
|
||||
----
|
||||
@ -31,7 +31,7 @@ Ein komplettes Programm zum Kompilieren hätte also den folgenden Inhalt:
|
||||
|
||||
|
||||
~*In[3]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn main() {
|
||||
println!("Hello world!");
|
||||
@ -40,7 +40,7 @@ fn main() {
|
||||
|
||||
Kompiliert und ausgeführt wird es dann über folgende Befehle:
|
||||
|
||||
[source,bash]
|
||||
[source, bash]
|
||||
----
|
||||
$ rustc main.rs
|
||||
$ ./main
|
||||
|
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-06-14T12:26:06.567Z
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= Cargo
|
||||
|
||||
@ -11,7 +11,7 @@ Cargo ist Rusts package manager. +
|
||||
Um ein neues Cargo-Projekt zu erstellen, braucht es das folgende
|
||||
Command:
|
||||
|
||||
[source,bash]
|
||||
[source, bash]
|
||||
----
|
||||
$ cargo new projektname --bin
|
||||
----
|
||||
@ -27,7 +27,7 @@ und `Cargo.toml` erstellt.
|
||||
|
||||
Unangetastet sieht die Datei so aus:
|
||||
|
||||
[source,toml]
|
||||
[source, toml]
|
||||
----
|
||||
[package]
|
||||
name = "projektname"
|
||||
@ -48,7 +48,7 @@ Die Main-Datei ist mit ``Hello World'' gefüllt.
|
||||
|
||||
=== cargo build
|
||||
|
||||
[source,bash]
|
||||
[source, bash]
|
||||
----
|
||||
$ cargo build
|
||||
$ ./target/debug/projektname
|
||||
|
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-06-14T12:27:14.473Z
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= Erstes Spiel
|
||||
|
||||
@ -13,7 +13,7 @@ Das Projekt wird wie in Notebook 01 beschrieben erstellt.
|
||||
|
||||
|
||||
~*In[2]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
:dep evcxr_input
|
||||
// Das ^ ist für Jupyter
|
||||
@ -69,7 +69,7 @@ auftreten
|
||||
Für eine random Zahl brauchen wir die erste Dependency. +
|
||||
Also `Cargo.toml` bearbeiten:
|
||||
|
||||
[source,toml]
|
||||
[source, toml]
|
||||
----
|
||||
[dependencies]
|
||||
rand = "0.3.14"
|
||||
@ -83,7 +83,7 @@ Die crate `rand` kann jetzt im Code verwendet werden.
|
||||
|
||||
|
||||
~*In[3]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
:dep rand = "0.3.15"
|
||||
// Das ^ ist von Jupyter
|
||||
@ -109,7 +109,7 @@ Ein Fehler?
|
||||
|
||||
|
||||
~*In[4]:*~
|
||||
[source, Rust]
|
||||
[source.notCompiling, rust]
|
||||
----
|
||||
use std::cmp::Ordering;
|
||||
|
||||
@ -138,7 +138,7 @@ Wir müssen unser guess also umwandeln:
|
||||
|
||||
|
||||
~*In[5]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let guess: u32 = guess.trim().parse().expect("Please type a number!");
|
||||
----
|
||||
@ -154,7 +154,7 @@ Jetzt sollte das Vergleichen auch klappen!
|
||||
|
||||
|
||||
~*In[6]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
use std::cmp::Ordering;
|
||||
|
||||
@ -178,7 +178,7 @@ Damit wir mehrmals raten können, brauchen wir eine Schleife.
|
||||
|
||||
|
||||
~*In[7]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let secret_number: u32 = rand::thread_rng().gen_range(1, 101);
|
||||
loop {
|
||||
@ -226,7 +226,7 @@ Offensichtlich müssen wir die Schleife dann abbrechen.
|
||||
|
||||
|
||||
~*In[8]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let secret_number: u32 = rand::thread_rng().gen_range(1, 101);
|
||||
loop {
|
||||
@ -277,7 +277,7 @@ Zahl eingibt. Das können wir auch relativ einfach fixen:
|
||||
|
||||
|
||||
~*In[9]:*~
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
loop {
|
||||
let mut guess = evcxr_input::get_string("Number? ");
|
||||
|
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-07-05T17:57:48+02:00
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= 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:
|
||||
|
||||
[source, Rust]
|
||||
[source.notCompiling, Rust]
|
||||
----
|
||||
fn main() {
|
||||
let x = "Hello world!";
|
||||
@ -25,7 +25,7 @@ fn main() {
|
||||
|
||||
Damit Variablen mutable sind, muss `mut` genutzt werden:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn main() {
|
||||
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:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
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.
|
||||
Ein Beispiel:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn main() {
|
||||
let x = 5;
|
||||
@ -86,7 +86,7 @@ Wenn das nicht geht, muss manuell ein Typ festgelegt werden.
|
||||
|
||||
Ein Beispiel:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
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
|
||||
- `saturating_add` bleibt beim Maximum oder Minimum des verfügbaren Bereiches
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let number: u8 = 254;
|
||||
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:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let x: (f32, char, u8) = (1.0, '🐧', 3);
|
||||
//_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:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let x: [i32; 5] = [1, 2, 3, 4, 5];
|
||||
// ^ so sieht der Datentyp aus
|
||||
@ -198,7 +198,7 @@ Sind wie normale Funktionen in C auch. Keyword ist `fn`.
|
||||
|
||||
Beispiel:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn calculate_sum(a: i32, b: i32) -> i64 {
|
||||
// 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:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn main() {
|
||||
'outer: loop {
|
||||
@ -253,7 +253,7 @@ fn main() {
|
||||
`break` mit Wert ist Rückgabe.
|
||||
Einfaches Beispiel:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn main() {
|
||||
let mut counter = 0;
|
||||
@ -279,7 +279,7 @@ fn main() {
|
||||
|
||||
Looped durch eine Collection (wie in Python).
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
fn main() {
|
||||
let a = [10, 20, 30, 40, 50];
|
||||
|
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-07-05T15:32:40+02:00
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= Ownership
|
||||
|
||||
@ -35,7 +35,7 @@ Dieser String-Typ hat den Vorteil, dass er eine dynamische Länge hat und damit
|
||||
|
||||
Ein Beispiel:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let mut x = String::from("Hello"); // Legt "dynamischen" String an
|
||||
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
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let x = 5; // Int -> feste Größe und auf Stack
|
||||
let y = x;
|
||||
@ -110,7 +110,7 @@ Damit werden (unter anderem) Race Conditions schon beim Compilen verhindert.
|
||||
|
||||
=== Dangling references
|
||||
|
||||
[source, Rust]
|
||||
[source.notCompiling, rust]
|
||||
----
|
||||
fn dangle() -> &String {
|
||||
let s = String::from("hello");
|
||||
@ -133,7 +133,7 @@ Nur so kann multithreading etc. funktionieren.
|
||||
Dafür hat Rust den Slice-Datentyp.
|
||||
Der funktioniert ähnlich wie Array-Ranges in Python.
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let s = String::from("hello world");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-07-05T17:45:24+02:00
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= Structs
|
||||
|
||||
@ -17,7 +17,7 @@ Man kann damit neue Datentypen machen.
|
||||
|
||||
=== "Normale" Structs
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
struct User {
|
||||
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:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
let user2 = User {
|
||||
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
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
struct RGBColor(u8, u8, u8);
|
||||
|
||||
@ -75,7 +75,7 @@ Sind nutzbar wie Tupel (destrucuture und `.index` zum Zugriff auf Werte), allerd
|
||||
|
||||
=== Unit-Like Structs
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
struct AlwaysEqual;
|
||||
----
|
||||
@ -119,7 +119,7 @@ Tatsächlich ist der sehr einfach und sehr OOPig.
|
||||
|
||||
Die folgenden Beispiele sollten relativ viel erklären:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
struct Rectangle {
|
||||
width: u32,
|
||||
@ -184,7 +184,7 @@ fn main() {
|
||||
Eine Methode kann auch `&mut self` als ersten Parameter haben.
|
||||
Dann können auch Felder geschrieben werden. In diesem Fall werden Referenzen aber invalidiert!
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
struct Rectangle {
|
||||
width: u32,
|
||||
|
@ -1,5 +1,5 @@
|
||||
:experimental:
|
||||
:docdatetime: 2022-07-25T20:00:23+02:00
|
||||
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||
|
||||
= 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`).
|
||||
Dieser ist entweder `None` oder `Some(value: T)` - es kann also ein Wert zusätzlich zur "Definition" beinhalten.
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
enum Farbcode {
|
||||
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:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
enum Farbcode {
|
||||
Hex(String),
|
||||
@ -54,7 +54,7 @@ Natürlich können die Structs jeder Art sein.
|
||||
Enums sind aber auch selber eine Art Struct.
|
||||
Also können wir für Enums auch Methoden definieren wie für Structs.
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
impl Farbcode {
|
||||
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.
|
||||
Diese Methode muss ja, je nach Typ, völlig unterschiedlich funktionieren.
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
enum Farbcode {
|
||||
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.
|
||||
Letzendlich ist es ganz simpel:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
#[derive(Debug)]
|
||||
enum Muenzwurf {
|
||||
|
@ -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.
|
||||
Ein Beispiel:
|
||||
|
||||
[source.notCompiling, Rust]
|
||||
[source.notCompiling, rust]
|
||||
----
|
||||
mod testmodul {
|
||||
mod nested_modul {
|
||||
@ -77,7 +77,7 @@ Das funktioniert noch *nicht*.
|
||||
Denn standardmäßig ist alles private, was nicht explizit public ist.
|
||||
Damit wir den obigen Aufruf machen können, muss der Code so aussehen:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
mod testmodul {
|
||||
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.
|
||||
So kann man folgendes machen:
|
||||
|
||||
[source, Rust]
|
||||
[source, rust]
|
||||
----
|
||||
mod testmodul {
|
||||
pub struct Teststruct {
|
||||
|
Loading…
Reference in New Issue
Block a user