Set up Cargo workspace with hello and variables examples
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "variables"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -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í)");
|
||||
}
|
||||
Reference in New Issue
Block a user