Set up Cargo workspace with hello and variables examples

This commit is contained in:
2026-10-18 11:46:43 +02:00
parent 53274ecb0b
commit d163a72e0f
7 changed files with 526 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
[package]
name = "hello"
version = "0.1.0"
edition = "2024"
[dependencies]
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("Nazdar!");
}
+6
View File
@@ -0,0 +1,6 @@
[package]
name = "variables"
version = "0.1.0"
edition = "2024"
[dependencies]
+484
View File
@@ -0,0 +1,484 @@
// Ukázka práce s proměnnými v Rustu.
// Každá sekce je ve vlastní funkci, main() je volá postupně.
// ---------------------------------------------------------------------------
// Konstanty a statické proměnné (definují se mimo funkce, globálně)
// ---------------------------------------------------------------------------
// `const` – hodnota známá při kompilaci, překladač ji vloží všude, kde se použije.
// Typ musí být uveden vždy. Název podle konvence VELKÝMI_PÍSMENY.
const MAX_BODU: u32 = 100;
// Konstanta může být vypočtena z jiných konstant (výpočet proběhne při kompilaci).
const SEKUND_ZA_DEN: u32 = 24 * 60 * 60;
// `static` – jedna pevná adresa v paměti po celou dobu běhu programu.
// Na rozdíl od `const` se nekopíruje, existuje právě jednou.
static NAZEV_PROGRAMU: &str = "Rust Playground";
fn main() {
zakladni_promenne();
mutabilita();
shadowing();
typy_a_anotace();
cisla_a_literaly();
preteceni();
pretypovani();
konstanty_a_static();
tuple_a_pole();
destrukturalizace();
odlozena_inicializace();
bloky_jako_vyrazy();
rozsah_platnosti();
vlastnictvi_move_a_copy();
reference();
retezce();
option_a_if_let();
let_else();
nepouzite_promenne();
}
// ---------------------------------------------------------------------------
// 1. Základní deklarace
// ---------------------------------------------------------------------------
fn zakladni_promenne() {
println!("\n== 1. Základní proměnné ==");
// `let` vytvoří proměnnou. Ve výchozím stavu je NEMĚNNÁ (immutable).
let x = 5;
println!("x = {x}");
// x = 6; // CHYBA: cannot assign twice to immutable variable
// Typ si překladač odvodí sám (type inference) – tady i32 (výchozí pro celá čísla).
let y = 2.5; // f64 (výchozí pro desetinná čísla)
println!("y = {y}");
}
// ---------------------------------------------------------------------------
// 2. Měnitelné proměnné
// ---------------------------------------------------------------------------
fn mutabilita() {
println!("\n== 2. Mutabilita ==");
// `mut` povolí změnu hodnoty. Typ se ale měnit nesmí.
let mut pocitadlo = 0;
println!("pocitadlo = {pocitadlo}");
pocitadlo += 1;
pocitadlo *= 10;
println!("pocitadlo po změnách = {pocitadlo}");
// pocitadlo = "text"; // CHYBA: mismatched types – typ je pevně i32
}
// ---------------------------------------------------------------------------
// 3. Shadowing (zastínění)
// ---------------------------------------------------------------------------
fn shadowing() {
println!("\n== 3. Shadowing ==");
// Novým `let` se stejným jménem vytvoříme NOVOU proměnnou, která tu starou zastíní.
let hodnota = 5;
let hodnota = hodnota + 1; // nová proměnná, stará už není dostupná
println!("hodnota = {hodnota}");
// Shadowing umí (na rozdíl od `mut`) změnit i typ.
let mezery = " "; // &str
let mezery = mezery.len(); // usize
println!("počet mezer = {mezery}");
// Shadowing ve vnořeném bloku platí jen uvnitř bloku.
let z = 1;
{
let z = z * 100;
println!("z uvnitř bloku = {z}");
}
println!("z mimo blok = {z}");
}
// ---------------------------------------------------------------------------
// 4. Explicitní typy
// ---------------------------------------------------------------------------
fn typy_a_anotace() {
println!("\n== 4. Typy a anotace ==");
// Typ lze uvést za dvojtečku.
let a: i64 = 42;
let b: f32 = 2.5;
let c: bool = true;
let d: char = 'ř'; // char je Unicode znak (4 bajty), píše se v jednoduchých uvozovkách
let e: () = (); // "unit" – prázdná hodnota, obdoba void
println!("a={a}, b={b}, c={c}, d={d}, e={e:?}");
// Někdy je anotace nutná, protože překladač nemá z čeho typ odvodit.
let cislo: u8 = "200".parse().expect("není číslo");
// Alternativa: typ zadaný přes "turbofish" ::<>
let cislo2 = "300".parse::<u16>().expect("není číslo");
println!("cislo={cislo}, cislo2={cislo2}");
}
// ---------------------------------------------------------------------------
// 5. Číselné typy a zápisy literálů
// ---------------------------------------------------------------------------
fn cisla_a_literaly() {
println!("\n== 5. Čísla a literály ==");
// Celá čísla se znaménkem: i8, i16, i32, i64, i128, isize
// Bez znaménka: u8, u16, u32, u64, u128, usize
// isize/usize mají velikost podle architektury (na 64bit = 64 bitů), usize se používá pro indexy.
println!("i8: {} až {}", i8::MIN, i8::MAX);
println!("u64: {} až {}", u64::MIN, u64::MAX);
// Různé zápisy literálů:
let desitkove = 1_000_000; // podtržítka pro čitelnost
let hex = 0xFF;
let oktal = 0o77;
let binarni = 0b1010_1010;
let bajt = b'A'; // u8, jen ASCII
let s_priponou = 42u8; // typ přímo v literálu
let float = 1e3; // 1000.0 (f64)
println!("{desitkove} {hex} {oktal} {binarni} {bajt} {s_priponou} {float}");
}
// ---------------------------------------------------------------------------
// 6. Přetečení
// ---------------------------------------------------------------------------
fn preteceni() {
println!("\n== 6. Přetečení ==");
let x: u8 = 250;
// let y = x + 10; // v debug režimu PANIKA (overflow), v release se tiše "přetočí"
// Proto existují metody, kterými chování určíš explicitně:
println!("wrapping_add: {}", x.wrapping_add(10)); // 4 – přetočí se
println!("checked_add: {:?}", x.checked_add(10)); // None – přetečení
println!("saturating_add: {}", x.saturating_add(10)); // 255 – zastaví se na max
println!("overflowing_add:{:?}", x.overflowing_add(10)); // (4, true)
}
// ---------------------------------------------------------------------------
// 7. Přetypování
// ---------------------------------------------------------------------------
fn pretypovani() {
println!("\n== 7. Přetypování ==");
// Rust NIKDY nepřetypovává čísla automaticky, musí se to napsat.
let a: i32 = 10;
let b: i64 = 20;
// let c = a + b; // CHYBA: mismatched types
// `as` – rychlé, ale může tiše ořezat hodnotu
let c = a as i64 + b;
let orez = 300_i32 as u8; // 300 se nevejde do u8 -> 44
let desetinne = 3.99_f64 as i32; // useknutí desetinné části -> 3
println!("c={c}, orez={orez}, desetinne={desetinne}");
// `From`/`Into` – bezpečný převod, existuje jen tam, kde nemůže dojít ke ztrátě
let velke: i64 = i64::from(a);
let velke2: i64 = a.into();
println!("velke={velke}, velke2={velke2}");
// `TryFrom`/`TryInto` – převod, který může selhat, vrací Result
let vysledek: Result<u8, _> = u8::try_from(300_i32);
println!("try_from(300) -> {vysledek:?}");
}
// ---------------------------------------------------------------------------
// 8. const a static
// ---------------------------------------------------------------------------
fn konstanty_a_static() {
println!("\n== 8. const a static ==");
println!("MAX_BODU = {MAX_BODU}");
println!("SEKUND_ZA_DEN = {SEKUND_ZA_DEN}");
println!("NAZEV_PROGRAMU = {NAZEV_PROGRAMU}");
// Konstantu lze definovat i lokálně uvnitř funkce.
const LOKALNI: f64 = 9.81;
println!("LOKALNI = {LOKALNI}");
// Pozn.: existuje i `static mut`, ale přístup k němu vyžaduje `unsafe`
// a v edici 2024 je silně omezen. Pro sdílený měnitelný stav se používají
// atomické typy (std::sync::atomic) nebo Mutex.
}
// ---------------------------------------------------------------------------
// 9. Složené typy: tuple a pole
// ---------------------------------------------------------------------------
fn tuple_a_pole() {
println!("\n== 9. Tuple a pole ==");
// Tuple – pevný počet prvků, každý může mít jiný typ.
let osoba: (&str, u32, bool) = ("Honza", 30, true);
println!("jméno={}, věk={}, aktivní={}", osoba.0, osoba.1, osoba.2);
// Pole – pevná délka (součást typu), všechny prvky stejného typu, leží na zásobníku.
let cisla: [i32; 5] = [1, 2, 3, 4, 5];
let nuly = [0; 3]; // [0, 0, 0] – 3× hodnota 0
println!("cisla={cisla:?}, první={}, délka={}", cisla[0], cisla.len());
println!("nuly={nuly:?}");
// Měnitelné pole
let mut pole = [10, 20, 30];
pole[1] = 99;
println!("pole={pole:?}");
// Vec – dynamické pole na haldě, může růst.
let mut v = vec![1, 2, 3];
v.push(4);
println!("vec={v:?}");
}
// ---------------------------------------------------------------------------
// 10. Destrukturalizace (rozbalení do více proměnných)
// ---------------------------------------------------------------------------
fn destrukturalizace() {
println!("\n== 10. Destrukturalizace ==");
// Tuple
let (x, y, z) = (1, 2.0, 'a');
println!("x={x}, y={y}, z={z}");
// `_` ignoruje hodnotu
let (prvni, _, treti) = (10, 20, 30);
println!("prvni={prvni}, treti={treti}");
// Pole
let [a, b, c] = [1, 2, 3];
println!("a={a}, b={b}, c={c}");
// `..` ignoruje zbytek
let [zacatek, .., konec] = [1, 2, 3, 4, 5];
println!("zacatek={zacatek}, konec={konec}");
// Struktura
struct Bod {
x: i32,
y: i32,
}
let bod = Bod { x: 3, y: 7 };
let Bod { x: bx, y: by } = bod; // přejmenování
println!("bx={bx}, by={by}");
// Přiřazení s destrukturalizací do existujících proměnných (prohození hodnot)
let mut m = 1;
let mut n = 2;
(m, n) = (n, m);
println!("m={m}, n={n}");
}
// ---------------------------------------------------------------------------
// 11. Odložená inicializace
// ---------------------------------------------------------------------------
// Clippy by tu radši viděl `let vysledek = if ...` (viz sekce 12), tady jde ale o ukázku.
#[allow(clippy::needless_late_init)]
fn odlozena_inicializace() {
println!("\n== 11. Odložená inicializace ==");
// Proměnnou lze deklarovat bez hodnoty a přiřadit ji později – ale jen JEDNOU
// a překladač hlídá, že se nepoužije dřív, než má hodnotu.
let vysledek: &str;
let teplota = 25;
if teplota > 20 {
vysledek = "teplo";
} else {
vysledek = "zima";
}
println!("je {vysledek}");
}
// ---------------------------------------------------------------------------
// 12. Bloky a if jako výrazy
// ---------------------------------------------------------------------------
fn bloky_jako_vyrazy() {
println!("\n== 12. Bloky jako výrazy ==");
// Blok { } vrací hodnotu posledního výrazu (bez středníku!).
let y = {
let x = 3;
x * x + 1 // bez středníku = návratová hodnota bloku
};
println!("y = {y}");
// `if` je výraz – idiomatičtější varianta příkladu z předchozí sekce.
let teplota = 15;
let popis = if teplota > 20 { "teplo" } else { "zima" };
println!("je {popis}");
// `match` je také výraz.
let znamka = 2;
let slovy = match znamka {
1 => "výborně",
2 => "chvalitebně",
3 => "dobře",
_ => "jiné",
};
println!("známka {znamka} = {slovy}");
// `loop` umí vrátit hodnotu přes `break`.
let mut i = 0;
let prvni_nad_50 = loop {
i += 7;
if i > 50 {
break i;
}
};
println!("první násobek 7 nad 50 = {prvni_nad_50}");
}
// ---------------------------------------------------------------------------
// 13. Rozsah platnosti (scope)
// ---------------------------------------------------------------------------
fn rozsah_platnosti() {
println!("\n== 13. Rozsah platnosti ==");
let venku = "venku";
{
let uvnitr = "uvnitř";
println!("{venku} i {uvnitr} jsou dostupné");
} // zde `uvnitr` zaniká (a uvolní se jeho paměť)
// println!("{uvnitr}"); // CHYBA: cannot find value `uvnitr` in this scope
println!("{venku} je stále dostupné");
}
// ---------------------------------------------------------------------------
// 14. Vlastnictví: move vs. copy
// ---------------------------------------------------------------------------
fn vlastnictvi_move_a_copy() {
println!("\n== 14. Move vs. copy ==");
// Jednoduché typy (čísla, bool, char, tuple/pole z nich) implementují `Copy`
// – přiřazení vytvoří kopii a obě proměnné jsou dál platné.
let a = 5;
let b = a;
println!("a={a}, b={b}");
// Typy na haldě (String, Vec, ...) se při přiřazení PŘESOUVAJÍ (move).
let s1 = String::from("ahoj");
let s2 = s1; // vlastnictví přešlo na s2
// println!("{s1}"); // CHYBA: borrow of moved value: `s1`
println!("s2={s2}");
// Pokud chceme skutečnou kopii, musíme explicitně zavolat `.clone()`.
let s3 = s2.clone();
println!("s2={s2}, s3={s3}");
}
// ---------------------------------------------------------------------------
// 15. Reference (půjčování)
// ---------------------------------------------------------------------------
fn reference() {
println!("\n== 15. Reference ==");
let text = String::from("Rust");
// `&` – neměnná reference. Těch může být libovolně mnoho současně.
let r1 = &text;
let r2 = &text;
println!("r1={r1}, r2={r2}, délka={}", delka(&text));
// `&mut` – měnitelná reference. Proměnná musí být `mut`
// a v jednu chvíli smí existovat JEN JEDNA (a žádná neměnná zároveň).
let mut cislo = 10;
{
let r = &mut cislo;
*r += 5; // `*` = dereference, přístup k hodnotě, na kterou reference ukazuje
}
println!("cislo={cislo}");
let mut seznam = vec![1, 2];
pridej(&mut seznam, 3);
println!("seznam={seznam:?}");
}
// Parametr je `&str`, ne `&String` – funkce pak přijme oba typy
// (`&String` se na `&str` převede automaticky, tzv. deref coercion).
fn delka(s: &str) -> usize {
s.len() // funkce si hodnotu jen půjčila, vlastnictví zůstává volajícímu
}
fn pridej(v: &mut Vec<i32>, hodnota: i32) {
v.push(hodnota);
}
// ---------------------------------------------------------------------------
// 16. Řetězce: &str vs String
// ---------------------------------------------------------------------------
fn retezce() {
println!("\n== 16. Řetězce ==");
// &str – "řez" řetězce, neměnný, často přímo v binárce (literály).
let pozdrav: &str = "Ahoj";
// String – vlastněný, měnitelný řetězec na haldě.
let mut jmeno = String::from("Hon");
jmeno.push_str("za");
jmeno.push('!');
// Převody
let z_str: String = pozdrav.to_string();
let jako_str: &str = &jmeno;
// Spojování
let veta = format!("{pozdrav}, {jmeno}");
println!("{veta} | {z_str} | {jako_str}");
// Raw string – bez escapování
let cesta = r"C:\Users\honza";
println!("{cesta}");
}
// ---------------------------------------------------------------------------
// 17. Option a if let
// ---------------------------------------------------------------------------
fn option_a_if_let() {
println!("\n== 17. Option a if let ==");
// Rust nemá null. Chybějící hodnota se vyjadřuje typem Option<T>.
let neco: Option<i32> = Some(42);
let nic: Option<i32> = "abc".parse().ok(); // parsování selže -> None
// `if let` – rozbalení hodnoty, pokud odpovídá vzoru
if let Some(hodnota) = neco {
println!("neco obsahuje {hodnota}");
}
// Výchozí hodnota, pokud je None
let s_vychozi = nic.unwrap_or(0);
println!("nic s výchozí hodnotou = {s_vychozi}");
}
// ---------------------------------------------------------------------------
// 18. let-else
// ---------------------------------------------------------------------------
fn let_else() {
println!("\n== 18. let-else ==");
// `let ... else` – rozbalí hodnotu, a pokud vzor nesedí, MUSÍ blok else
// z funkce odejít (return, break, continue, panic).
let vstup = "123";
let Ok(cislo) = vstup.parse::<i32>() else {
println!("'{vstup}' není číslo");
return;
};
println!("načteno číslo {cislo}");
}
// ---------------------------------------------------------------------------
// 19. Nepoužité proměnné
// ---------------------------------------------------------------------------
fn nepouzite_promenne() {
println!("\n== 19. Nepoužité proměnné ==");
// Překladač varuje u nepoužitých proměnných. Podtržítko na začátku varování potlačí.
let _zatim_nepouzito = 10;
// Samotné `_` hodnotu vůbec nesváže (a u typů na haldě ji rovnou zahodí).
let _ = String::from("zahozeno");
println!("(žádné varování)");
}