Hlavní navigace

Práce s poli v programovacím jazyku Rust

Pavel Tišnovský

V jedenácté části seriálu o programovacím jazyku Rust se budeme zabývat způsobem práce s poli, což je sice zdánlivě triviální téma, ovšem některé koncepty práce s poli jsou v Rustu specifické.

Obsah

1. Konstruktor pro vytvoření pole

2. Kontrola překročení mezí polí

3. Vytvoření pole opakováním jediného prvku

4. Změna prvku v poli: rozdíl mezi neměnitelným a měnitelným polem

5. Použití iterátoru pro průchod všemi prvky pole

6. Vytvoření „řezu“ z pole

7. Automatický výpočet horního či dolního indexu při tvorbě „řezu“

8. Pokus o prohození horního a dolního indexu

9. Výpočet „řezu“ v době běhu programu

10. Explicitní specifikace typů a počtu prvků v poli

11. Specifikace pouze počtu prvků, automatické odvození jejich typů

12. Alternativní možnost získání iterátoru pro krátké pole

13. Dvourozměrná a vícerozměrná pole

14. Použití indexů pro přístup k prvkům vícerozměrných polí

15. Iterace přes prvky vícerozměrných polí

16. Repositář s demonstračními příklady

17. Odkazy na Internetu

1. Konstruktor pro vytvoření pole

Základní práce s poli není v Rustu nic těžkého, takže začněme velmi jednoduchým příkladem, v němž si ukážeme způsob deklarace pole s konstantním počtem prvků a následně výpis prvků z vytvořeného pole. Nejjednodušším způsobem, jako pole vytvořit, je vypsat hodnoty všech jeho prvků a umístit je mezi hranaté závorky. Pozor tedy na první podstatný rozdíl oproti některým dalším céčkovým jazykům, v nichž se prvky uzavírají do složených závorek. Toto pole má konstantní délku a je neměnné. Současně se jedná o objekt, který lze bez problémů přiřadit do lokální proměnné, u které není nutné uvádět žádný typ, protože se díky typové inferenci typ automaticky odvodí. Ve druhé části příkladu se v počítané programové smyčce nastavuje hodnota počitadla i na indexy prvků pole. Povšimněte si, jakým způsobem se zjišťuje počet prvků pole metodou len() a jak se přistupuje k i-tému prvku (zde se žádné větší překvapení nekoná):

fn main() {
    let array = [10, 20, 30, 40];
 
    println!("array has {} items", array.len());
 
    for i in 0..array.len() {
        println!("item #{} = {}", i+1, array[i]);
    }
}

Výsledek spuštění tohoto příkladu:

array has 4 items
item #1 = 10
item #2 = 20
item #3 = 30
item #4 = 40

2. Konstruktor pro vytvoření pole

Jak je to s kontrolou mezí polí? Některé problémy zjistí již překladač, například použití záporného indexu:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    println!("{}", array[2]);
    println!("{}", array[-1]);
}

Zde dojde k chybě při překladu, protože se snažíme z kladného celého čísla získat číslo záporné bez přetypování:

error[E0080]: constant evaluation error
 --> test.rs:5:26
  |
5 |     println!("{}", array[-1]);
  |                          ^^ unary negation of unsigned integer
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
test.rs:5:5: 5:31 note: in this expansion of println! (defined in <std macros>)
 
error: aborting due to previous error

Zajímavější je situace při použití indexu, který překračuje meze pole. Index může být známý v době překladu – potom překladač vypíše varování (nikoli chybu!):

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    println!("{}", array[2]);
    println!("{}", array[100]);
}
warning: this expression will panic at run-time
 --> test.rs:5:20
  |
5 |     println!("{}", array[100]);
  |                    ^^^^^^^^^^ index out of bounds: the len is 10 but the index is 100
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
test.rs:5:5: 5:32 note: in this expansion of println! (defined in <std macros>)

Chyba v tomto případě nastane až při běhu programu:

thread 'main' panicked at 'index out of bounds: the len is 10 but the index is 100', test.rs:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Někdy ovšem překladač neví a ani nemůže zjistit, jaký index vlastně použijeme. V následujícím příkladu se index vypočte na základě počtu proměnných prostředí (ve standardní knihovně není funkce pro náhodná čísla, takže toto je pravděpodobně nejjednodušší způsob, jak získat hodnotu, která není známá v době překladu):

use std::env;
 
fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    let env_vars = env::vars_os();
 
    let index = env_vars.count() + 100;
 
    println!("{}", array[2]);
    println!("{}", array[index]);
}

Příklad běhové chyby (konkrétní použitý index se samozřejmě bude ve vašem případě odlišovat):

thread 'main' panicked at 'index out of bounds: the len is 10 but the index is 174', test.rs:11
note: Run with `RUST_BACKTRACE=1` for a backtrace.

3. Vytvoření pole opakováním jediného prvku

Existuje ještě jedna možnost vytvoření pole. Pokud potřebujeme pracovat s polem, v němž se nachází prvky se shodnou hodnotou, je možné použít tento zápis:

[hodnota_prvků; počet_prvků]

Pozor na rozdíl oproti dvouprvkovému poli (rozdíl spočívá v použití středníku, popř. čárky):

[prvek_1, prvek_2]

Přesvědčme se, že vytvořené pole skutečně obsahuje prvky se shodnou hodnotou:

fn main() {
    let array = [1; 10];
 
    println!("array has {} items", array.len());
 
    for i in 0..array.len() {
        println!("item #{} = {}", i+1, array[i]);
    }
}

Po překladu a spuštění dostaneme tento výsledek:

array has 10 items
item #1 = 1
item #2 = 1
item #3 = 1
item #4 = 1
item #5 = 1
item #6 = 1
item #7 = 1
item #8 = 1
item #9 = 1
item #10 = 1

4. Změna prvku v poli: rozdíl mezi neměnitelným a měnitelným polem

Z předchozích dvou příkladů je patrné, jak se přistupuje k prvkům pole. Co se ovšem stane ve chvíli, kdy se namísto čtení prvku pokusíme nějaký prvek změnit?

fn main() {
    let array = [10, 20, 30, 40];
 
    array[1] = 42;
 
    for i in 0..array.len() {
        println!("item #{} = {}", i+1, array[i]);
    }
}

Při pokusu o překlad dojde k chybě, která je vlastně pochopitelná, a to z toho důvodu, že pole je, podobně jako další objekty, ve výchozím stavu neměnitelné (stačí si vzpomenout, že jsme stejný problém řešili i našeho objektu s komplexními čísly):

error: cannot assign to immutable indexed content `array[..]`
 --> 134_immutable_array.rs:4:5
  |
4 |     array[1] = 42;
  |     ^^^^^^^^^^^^^
 
error: aborting due to previous error

Náprava tohoto problému je velmi jednoduchá, stačí použít nám již známý modifikátor mut:

fn main() {
    let mut array = [10, 20, 30, 40];
 
    array[1] = 42;
 
    for i in 0..array.len() {
        println!("item #{} = {}", i+1, array[i]);
    }
}

Nyní již zápis (modifikace) pole proběhne bez problémů:

item #1 = 10
item #2 = 42
item #3 = 30
item #4 = 40

5. Použití iterátoru pro průchod všemi prvky pole

Pro pole je možné získat iterátor, a to pomocí metody iter(). Typické použití iterátoru je při průchodu všemi prvky pole:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let iterator = array.iter();
 
    for i in iterator {
        println!("{}", i);
    }
}

Většinou není nutné iterátor explicitně ukládat do proměnné, navíc by měla mít proměnná iterator jinou oblast viditelnosti, než jsme použili (pouze pro programovou smyčku). Následující kód je pro Rust idiomatický:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    for i in array.iter() {
        println!("{}", i);
    }
}

Spuštění příkladu:

1
2
3
4
5
6
7
8
9
10

Iterátor vytvořený pro pole dokáže procházet jeho obsahem i pozpátku (to ale nemusí platit pro všechny iterátory, někdy je povolen jen průchod jedním směrem):

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    for i in array.iter().rev() {
        println!("{}", i);
    }
}

Spuštění příkladu:

10
9
8
7
6
5
4
3
2
1

6. Vytvoření „řezu“ z pole

Samotná práce s polem tak, jak jsme si ji ukázali v předchozích příkladech, vlastně kromě možnosti použití iterátoru nepřináší žádné podstatně nové vlastnosti. V Rustu však můžeme z pole vytvořit „řez“, a to podobným způsobem, s jakým jsme se setkali při práci s řetězci. Způsob specifikace prvků, které mají být umístěny v řezu, je následující:

pole[min..max]

Ovšem je nutné dát si pozor na to, že mezi řezem pole a samotným polem je jeden podstatný rozdíl – u pole je nutné znát velikost při překladu (mj. i proto, aby správně fungovala správa paměti), zatímco u řezu se tyto informace mohou zjišťovat až při běhu programu. Proto následující příklad nepůjde přeložit, i když je syntakticky správně:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = array[2..6];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

Překladač vypíše toto chybové hlášení:

error[E0277]: the trait bound `[{integer}]: std::marker::Sized` is not satisfied
 --> 138_array_slice_incorrect.rs:3:9
  |
3 |     let array2 = array[2..6];
  |         ^^^^^^
  |
  = note: `[{integer}]` does not have a constant size known at compile-time
  = note: all local variables must have a statically known size
 
error: aborting due to previous error

Řešením je použití znaku & (reference). Interně je totiž „řez“ reprezentován objektem obsahujícím ukazatel na pole (resp. na první prvek v řezu) a délku řezu. Následující příklad je již zapsán korektně a půjde přeložit:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[2..6];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

Spuštění příkladu:

3
4
5
6

Díky tomu, že řez je vlastně jen pohled (view) do vlastního pole, je vytvoření řezu velmi efektivní operace a samozřejmě je možné vytvářet řezy řezů (nezapomeňte na to, že meze se vždy vztahují k té struktuře, ze které se řez vytváří a nikoli k původnímu poli):

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[2..8];
    let array3 = &array2[2..4];
 
    for i in array3.iter() {
        println!("{}", i);
    }
}

7. Automatický výpočet horního či dolního indexu při tvorbě „řezu“

Ve skutečnosti je možné při deklaraci „řezu“ vynechat dolní mez, horní mez či obě meze. V takovém případě se do dolní meze automaticky dosadí nula a do horní meze pole.len()-1. Vše je velmi jednoduché, ostatně se jedná o podobný koncept, který nalezneme i v dalších programovacích jazycích, takže další tři příklady nebudou vyžadovat delší povídání:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[5..];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

Spuštění příkladu:

6
7
8
9
10
fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[..5];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

Spuštění příkladu:

1
2
3
4
5
fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[..];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

Spuštění příkladu:

1
2
3
4
5
6
7
8
9
10

8. Pokus o prohození horního a dolního indexu

Pokud se pokusíme prohodit horní a dolní index, nebude překladač nic namítat, protože obecně platí, že meze řezů jsou zjišťovány až v čase běhu programu. Následující příklad se tedy přeloží:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[8..2];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

Ovšem při spuštění dojde k běhové chybě:

thread 'main' panicked at 'slice index starts at 8 but ends at 2', ../src/libcore/slice.rs:555
note: Run with `RUST_BACKTRACE=1` for a backtrace.

9. Výpočet „řezu“ v době běhu programu

V úvodní kapitole jsme si řekli, že velikost pole je známá již v době překladu. Ovšem u řezů tomu tak být nemusí, takže dolní i horní mez je možné vypočítat až v čase běhu programu. Následující demonstrační příklad je poněkud umělý, a to opět z toho důvodu, že ve standardní knihovně není obsažena funkce pro generování náhodných čísel a bylo by nutné vytvářet projekt (což je u takto krátkých příkladů pravděpodobně zbytečné):

use std::env;
 
fn main() {
    let env_vars = env::vars_os();
 
    let min = env_vars.count() % 5;
    let max = min + 5;
 
    println!("min: {}", min);
    println!("max: {}", max);
 
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let array2 = &array[min..max];
 
    for i in array2.iter() {
        println!("{}", i);
    }
}

10. Explicitní specifikace typů a počtu prvků v poli

V některých případech je nutné specifikovat typ a popř. i počet prvků v poli. Jedná se o úplné určení typu pole a používá se pro něj zápis:

[typ_prvku; počet_prvků]))

Typ se zapisuje za jméno proměnné (či parametru funkce) a je od ní oddělen dvojtečkou:

fn main() {
    let array : [i32; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    for i in array.iter() {
        println!("{}", i);
    }
}

Pokud se kombinuje specifikace typu pole a současně i jeho inicializace, je počet prvků kontrolován. Nemůže být ani menší:

fn main() {
    let array : [i32; 20] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    for i in array.iter() {
        println!("{}", i);
    }
}

Chyba při překladu:

error[E0308]: mismatched types
 --> 146_array_type_specifier_few_items.rs:2:29
  |
2 |     let array : [i32; 20] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 20 elements, found one with 10 elements
  |
  = note: expected type `[i32; 20]`
  = note:    found type `[i32; 10]`
 
error: aborting due to previous error

Ale nemůže být ani větší:

fn main() {
    let array : [i32; 5] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    for i in array.iter() {
        println!("{}", i);
    }
}

Chyba při překladu:

error[E0308]: mismatched types
 --> 147_array_type_specifier_more_items.rs:2:28
  |
2 |     let array : [i32; 5] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 5 elements, found one with 10 elements
  |
  = note: expected type `[i32; 5]`
  = note:    found type `[i32; 10]`
 
error: aborting due to previous error

11. Specifikace pouze počtu prvků, automatické odvození jejich typů

V některých případech je možné specifikovat pouze počet prvků a nechat překladač, aby si sám odvodil typ prvků pole. Namísto uvedení typu se použije znak podtržítka. Následující příklad je sice poněkud umělý, ale uvedený zápis se může hodit například při deklaraci funkcí vracejících pole, jehož typ je určen až ve chvíli, kdy je funkce volána:

fn main() {
    let array : [_; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    for i in array.iter() {
        println!("{}", i);
    }
}

Kdy se vůbec uvádí počet prvků? Příkladem může být vytvoření „prázdného“ pole, což je příklad, který se do značné míry podobá céčkové alokaci dynamického pole:

use std::mem;
 
fn main() {
    let mut array : [i32; 2] = unsafe{mem::uninitialized()};
 
    array[0] = 100;
    array[1] = 200;
 
    println!("{}", array[0]);
    println!("{}", array[1]);
}

S významem bloku „unsafe“ se ještě seznámíme.

12. Alternativní možnost získání iterátoru pro krátké pole

Zajímavé a v některých případech užitečné může být získání iterátoru pro krátké pole pouze s použitím znaku &. To je umožněno díky implementaci traitu IntoIterator, ovšem kvůli omezení současných překladačů je možné zkrácený zápis použít pouze u polí, které mají maximálně 32 prvků. Následující příklad tedy bude funkční:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
    println!("array has {} items", array.len());
 
    for i in &array {
        println!("{}", i);
    }
}

V dalším příkladu již máme pole se čtyřiceti prvky, takže tento příklad nepůjde přeložit:

fn main() {
    let array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    ];
 
    println!("array has {} items", array.len());
 
    for i in &array {
        println!("{}", i);
    }
}

Chyba při překladu:

error[E0277]: the trait bound `&[{integer}; 40]: std::iter::Iterator` is not satisfied
  --> 150_array_into_iterator_too_big.rs:10:5
   |
10 |     for i in &array {
   |     ^
   |
   = note: `&[{integer}; 40]` is not an iterator; maybe try calling `.iter()` or a similar method
   = note: required by `std::iter::IntoIterator::into_iter`
 
error: aborting due to previous error

13. Dvourozměrná a vícerozměrná pole

V programovacím jazyku Rust je samozřejmě možné kromě běžných jednorozměrných polí použít i pole s větším počtem rozměrů. Musí se však jednat o matice, tj. počet prvků v každém řádku pole musí být konstantní. Pokud tato vlastnost není vyhovující, je lepší namísto polí použít objekty typu vektor (tyto objekty si popíšeme v navazujícím článku).

14. Použití indexů pro přístup k prvkům vícerozměrných polí

Inicializace dvourozměrného pole je velmi jednoduchá, nesmíme pouze zapomenout na použití hranatých závorek. Ve druhé části příkladu je ukázáno, jak je možné přistupovat k prvkům dvourozměrného pole (zde uvedený zápis není pro Rust idiomatický). Přístup k prvkům dvourozměrného pole je stejný, jako například v céčku:

fn main() {
    let array = [[1,2,3,4],
                 [5,6,7,8],
                 [9,10,11,12]];
 
    println!("array has {} items", array.len());
 
    for i in 0..array.len() {
        for j in 0..array[i].len() {
            print!("{}\t", array[i][j]);
        }
        println!("");
    }
}

Ověřme si, zda překladač kontroluje fakt, že je skutečně zadána matice. Druhý řádek pole je delší:

fn main() {
    let array = [[1,2,3,4],
                 [5,6,7,8,0,0,0,0],
                 [9,10,11,12]];
 
    println!("array has {} items", array.len());
 
    for i in 0..array.len() {
        for j in 0..array[i].len() {
            print!("{}\t", array[i][j]);
        }
        println!("");
    }
}

Tato chyba je skutečně nalezena:

error[E0308]: mismatched types
 --> 151_matrix.rs:3:18
  |
3 |                  [5,6,7,8,0,0,0,0],
  |                  ^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 4 elements, found one with 8 elements
  |
  = note: expected type `[{integer}; 4]`
  = note:    found type `[{integer}; 8]`
 
error: aborting due to previous error

15. Iterace přes prvky vícerozměrných polí

V dnešním posledním příkladu je ukázáno, jakým způsobem se většinou prochází prvky dvourozměrného pole s použitím iterátorů. Ve vnější programové smyčce jsem použil zkrácený způsob získání iterátoru, který ovšem platí pouze pro matice s maximálně 32 řádky. Ve vnitřní smyčce se již používá explicitní získání iterátoru pro vybraný řádek:

fn main() {
    let array = [[1,2,3,4],
                 [5,6,7,8],
                 [9,10,11,12]];
 
    println!("array has {} items", array.len());
 
    for vector in &array {
        for item in vector.iter() {
            print!("{}\t", item);
        }
        println!("");
    }
}

16. Repositář s demonstračními příklady

Všechny dnes popisované demonstrační příklady byly, podobně jako ve všech předchozích částech tohoto seriálu, uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/pre­sentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář:

Příklad Odkaz
132_new_array.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/132_new_array.rs
133_new_array_repeat_item.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/133_new_array_repeat_item­.rs
134_immutable_array.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/134_immutable_array.rs
135_mutable_array.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/135_mutable_array.rs
136_foreach_array.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/136_foreach_array.rs
137_foreach_array_reverse.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/137_foreach_array_rever­se.rs
138_array_slice_incorrect.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/138_array_slice_incorrec­t.rs
139_array_slice_correct.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/139_array_slice_correct­.rs
140_array_slice_no_upper_limit.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/140_array_slice_no_upper_li­mit.rs
141_array_slice_no_lower_limit.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/141_array_slice_no_lower_li­mit.rs
142_array_slice_no_limits.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/142_array_slice_no_limit­s.rs
143_array_slice_reverse_limits.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/143_array_slice_reverse_li­mits.rs
144_array_slice_limits_at_runtime.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/144_array_slice_limits_at_run­time.rs
145_array_type_specifier.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/145_array_type_specifier­.rs
146_array_type_specifier_few_items.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/146_array_type_specifier_few_i­tems.rs
147_array_type_specifier_more_items.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/147_array_type_specifier_mo­re_items.rs
148_array_infer_type.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/148_array_infer_type.rs
149_array_into_iterator.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/149_array_into_iterator­.rs
150_array_into_iterator_too_big.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/150_array_into_iterator_to­o_big.rs
151_matrix.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/151_matrix.rs
152_matrix_iterators.rs https://github.com/tisnik/pre­sentations/blob/master/rus­t/152_matrix_iterators.rs

17. Odkazy na Internetu

  1. Primitive Type array
    https://doc.rust-lang.org/nightly/std/primi­tive.array.html
  2. Module std::slice
    https://doc.rust-lang.org/nightly/std/slice/
  3. Rust by Example: 2.3 Arrays and Slices
    http://rustbyexample.com/pri­mitives/array.html
  4. What is the difference between Slice and Array (stackoverflow)
    http://stackoverflow.com/qu­estions/30794235/what-is-the-difference-between-slice-and-array
  5. Learning Rust With Entirely Too Many Linked Lists
    http://cglab.ca/~abeinges/blah/too-many-lists/book/
  6. Testcase: linked list
    http://rustbyexample.com/cus­tom_types/enum/testcase_lin­ked_list.html
  7. Operators and Overloading
    https://doc.rust-lang.org/book/operators-and-overloading.html
  8. Module std::ops
    https://doc.rust-lang.org/std/ops/index.html
  9. Module std::cmp
    https://doc.rust-lang.org/std/cmp/index.html
  10. Trait std::ops::Add
    https://doc.rust-lang.org/stable/std/ops/trait.Add.html
  11. Trait std::ops::AddAssign
    https://doc.rust-lang.org/std/ops/trait.AddAssign.html
  12. Trait std::ops::Drop
    https://doc.rust-lang.org/std/ops/trait.Drop.html
  13. Trait std::cmp::Eq
    https://doc.rust-lang.org/std/cmp/trait.Eq.html
  14. Struct std::boxed::Box
    https://doc.rust-lang.org/std/boxed/struct.Box.html
  15. Explore the ownership system in Rust
    https://nercury.github.io/rus­t/guide/2015/01/19/ownership­.html
  16. Rust's ownership and move semantic
    http://www.slideshare.net/sa­neyuki/rusts-ownership-and-move-semantics
  17. Trait std::marker::Copy
    https://doc.rust-lang.org/stable/std/marker/tra­it.Copy.html
  18. Trait std::clone::Clone
    https://doc.rust-lang.org/stable/std/clone/tra­it.Clone.html
  19. The Stack and the Heap
    https://doc.rust-lang.org/book/the-stack-and-the-heap.html
  20. Rust Compare: Pointers & References
    http://www.rust-compare.com/site/pointers.html
  21. Rust Compare: Parameters
    http://www.rust-compare.com/site/params.html
  22. Why does this compile? Automatic dereferencing?
    https://users.rust-lang.org/t/why-does-this-compile-automatic-dereferencing/2183
  23. Understanding Pointers, Ownership, and Lifetimes in Rust
    http://koerbitz.me/posts/Understanding-Pointers-Ownership-and-Lifetimes-in-Rust.html
  24. Rust lang series episode #25 — pointers (#rust-series)
    https://steemit.com/rust-series/@jimmco/rust-lang-series-episode-25-pointers-rust-series
  25. Rust – home page
    https://www.rust-lang.org/en-US/
  26. Rust – Frequently Asked Questions
    https://www.rust-lang.org/en-US/faq.html
  27. Destructuring and Pattern Matching
    https://pzol.github.io/get­ting_rusty/posts/20140417_des­tructuring_in_rust/
  28. The Rust Programming Language
    https://doc.rust-lang.org/book/
  29. Rust (programming language)
    https://en.wikipedia.org/wi­ki/Rust_%28programming_lan­guage%29
  30. Go – home page
    https://golang.org/
  31. Stack Overflow – Most Loved, Dreaded, and Wanted language
    https://stackoverflow.com/re­search/developer-survey-2016#technology-most-loved-dreaded-and-wanted
  32. Rust vs Go (dva roky staré hodnocení, od té doby došlo k posunům v obou jazycích)
    http://jaredforsyth.com/2014/03/22/rust-vs-go/
  33. Rust vs Go: My experience
    https://www.reddit.com/r/go­lang/comments/21m6jq/rust_vs_go_my_ex­perience/
  34. Friends of Rust (Organizations running Rust in production)
    https://www.rust-lang.org/en-US/friends.html
  35. Rust programs versus C++ g++
    https://benchmarksgame.ali­oth.debian.org/u64q/compa­re.php?lang=rust&lang2=gpp
  36. Další benchmarky (nejedná se o reálné příklady „ze života“)
    https://github.com/kostya/benchmarks
  37. Go na Redditu
    https://www.reddit.com/r/golang/
  38. Rust vs. Go
    http://vschart.com/compare/rust/vs/go-language
  39. Abstraction without overhead: traits in Rust
    https://blog.rust-lang.org/2015/05/11/traits.html
  40. Method Syntax
    https://doc.rust-lang.org/book/method-syntax.html
  41. Traits in Rust
    https://doc.rust-lang.org/book/traits.html
  42. Functional Programming in Rust – Part 1 : Function Abstraction
    http://blog.madhukaraphatak­.com/functional-programming-in-rust-part-1/
  43. Of the emerging systems languages Rust, D, Go and Nim, which is the strongest language and why?
    https://www.quora.com/Of-the-emerging-systems-languages-Rust-D-Go-and-Nim-which-is-the-strongest-language-and-why
  44. Chytré ukazatele (moderní verze jazyka C++) [MSDN]
    https://msdn.microsoft.com/cs-cz/library/hh279674.aspx
  45. UTF-8 Everywhere
    http://utf8everywhere.org/
  46. Rust by Example
    http://rustbyexample.com/
  47. Rust oficiálně ve Fedoře
    https://mojefedora.cz/rust-oficialne-ve-fedore/
  48. Resource acquisition is initialization
    https://en.wikipedia.org/wi­ki/Resource_acquisition_is_i­nitialization
  49. TIOBE index (October 2016)
    http://www.tiobe.com/tiobe-index/
  50. Porovnání Go, D a Rustu na OpenHubu:
    https://www.openhub.net/lan­guages/compare?language_na­me[]=-1&language_name[]=-1&language_name[]=dmd&lan­guage_name[]=golang&langu­age_name[]=rust&language_na­me[]=-1&measure=commits
  51. String Types in Rust
    http://www.suspectsemantic­s.com/blog/2016/03/27/str­ing-types-in-rust/
  52. Trait (computer programming)
    https://en.wikipedia.org/wi­ki/Trait_%28computer_program­ming%29
  53. Type inference
    https://en.wikipedia.org/wi­ki/Type_inference
Našli jste v článku chybu?
3. 2. 2017 11:07

Nojo IT se v některých oblastech skutečně mění rychle (třeba ten zmíněný front-end, protože došlo k dost radikální změně v použití počítačů - už nejenom PC, ale hlavně client-server), na druhou stranu jsou pořád oblasti, které jsou velmi konzervativní. Často se zmiňuje finančnictví s COBOLem, ale je toho víc, oblast MCU a vůbec embedded věcí, řídicí jednotky, viděl jsem i dost složité a drahé přístroje s DOSem (vlastně proč ne) apod.

3. 2. 2017 16:32
yedpodtrzitko (neregistrovaný)

Ve vetsine programovacich jazyku se pouzivaji spis polootevrene intervaly, protoze se s nima lepe pracuje (viz tento priklad), a predejde se tak mj. i fencepost problemu. Priklad s Pythonim range() ktery generuje take polootevrene intervaly:

len(range(m)) == mlen(range(a, b)) == b - arange(a, a) == []range(a, b) + range(b, c) == range(a, c)