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
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
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/presentations. Příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář:
17. Odkazy na Internetu
- Primitive Type array
https://doc.rust-lang.org/nightly/std/primitive.array.html - Module std::slice
https://doc.rust-lang.org/nightly/std/slice/ - Rust by Example: 2.3 Arrays and Slices
http://rustbyexample.com/primitives/array.html - What is the difference between Slice and Array (stackoverflow)
http://stackoverflow.com/questions/30794235/what-is-the-difference-between-slice-and-array - Learning Rust With Entirely Too Many Linked Lists
http://cglab.ca/~abeinges/blah/too-many-lists/book/ - Testcase: linked list
http://rustbyexample.com/custom_types/enum/testcase_linked_list.html - Operators and Overloading
https://doc.rust-lang.org/book/operators-and-overloading.html - Module std::ops
https://doc.rust-lang.org/std/ops/index.html - Module std::cmp
https://doc.rust-lang.org/std/cmp/index.html - Trait std::ops::Add
https://doc.rust-lang.org/stable/std/ops/trait.Add.html - Trait std::ops::AddAssign
https://doc.rust-lang.org/std/ops/trait.AddAssign.html - Trait std::ops::Drop
https://doc.rust-lang.org/std/ops/trait.Drop.html - Trait std::cmp::Eq
https://doc.rust-lang.org/std/cmp/trait.Eq.html - Struct std::boxed::Box
https://doc.rust-lang.org/std/boxed/struct.Box.html - Explore the ownership system in Rust
https://nercury.github.io/rust/guide/2015/01/19/ownership.html - Rust's ownership and move semantic
http://www.slideshare.net/saneyuki/rusts-ownership-and-move-semantics - Trait std::marker::Copy
https://doc.rust-lang.org/stable/std/marker/trait.Copy.html - Trait std::clone::Clone
https://doc.rust-lang.org/stable/std/clone/trait.Clone.html - The Stack and the Heap
https://doc.rust-lang.org/book/the-stack-and-the-heap.html - Rust Compare: Pointers & References
http://www.rust-compare.com/site/pointers.html - Rust Compare: Parameters
http://www.rust-compare.com/site/params.html - Why does this compile? Automatic dereferencing?
https://users.rust-lang.org/t/why-does-this-compile-automatic-dereferencing/2183 - Understanding Pointers, Ownership, and Lifetimes in Rust
http://koerbitz.me/posts/Understanding-Pointers-Ownership-and-Lifetimes-in-Rust.html - Rust lang series episode #25 — pointers (#rust-series)
https://steemit.com/rust-series/@jimmco/rust-lang-series-episode-25-pointers-rust-series - Rust – home page
https://www.rust-lang.org/en-US/ - Rust – Frequently Asked Questions
https://www.rust-lang.org/en-US/faq.html - Destructuring and Pattern Matching
https://pzol.github.io/getting_rusty/posts/20140417_destructuring_in_rust/ - The Rust Programming Language
https://doc.rust-lang.org/book/ - Rust (programming language)
https://en.wikipedia.org/wiki/Rust_%28programming_language%29 - Go – home page
https://golang.org/ - Stack Overflow – Most Loved, Dreaded, and Wanted language
https://stackoverflow.com/research/developer-survey-2016#technology-most-loved-dreaded-and-wanted - 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/ - Rust vs Go: My experience
https://www.reddit.com/r/golang/comments/21m6jq/rust_vs_go_my_experience/ - Friends of Rust (Organizations running Rust in production)
https://www.rust-lang.org/en-US/friends.html - Rust programs versus C++ g++
https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=rust&lang2=gpp - Další benchmarky (nejedná se o reálné příklady „ze života“)
https://github.com/kostya/benchmarks - Go na Redditu
https://www.reddit.com/r/golang/ - Rust vs. Go
http://vschart.com/compare/rust/vs/go-language - Abstraction without overhead: traits in Rust
https://blog.rust-lang.org/2015/05/11/traits.html - Method Syntax
https://doc.rust-lang.org/book/method-syntax.html - Traits in Rust
https://doc.rust-lang.org/book/traits.html - Functional Programming in Rust – Part 1 : Function Abstraction
http://blog.madhukaraphatak.com/functional-programming-in-rust-part-1/ - 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 - Chytré ukazatele (moderní verze jazyka C++) [MSDN]
https://msdn.microsoft.com/cs-cz/library/hh279674.aspx - UTF-8 Everywhere
http://utf8everywhere.org/ - Rust by Example
http://rustbyexample.com/ - Rust oficiálně ve Fedoře
https://mojefedora.cz/rust-oficialne-ve-fedore/ - Resource acquisition is initialization
https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization - TIOBE index (October 2016)
http://www.tiobe.com/tiobe-index/ - Porovnání Go, D a Rustu na OpenHubu:
https://www.openhub.net/languages/compare?language_name[]=-1&language_name[]=-1&language_name[]=dmd&language_name[]=golang&language_name[]=rust&language_name[]=-1&measure=commits - String Types in Rust
http://www.suspectsemantics.com/blog/2016/03/27/string-types-in-rust/ - Trait (computer programming)
https://en.wikipedia.org/wiki/Trait_%28computer_programming%29 - Type inference
https://en.wikipedia.org/wiki/Type_inference