Obsah
1. Datové kolekce v programovacím jazyku Rust: množiny
2. Základní operace, které lze provádět s množinami
3. Vytvoření množiny implementované hešovací tabulkou
4. Vytvoření množiny implementované B-stromem
5. Operace insert() a remove()
6. Množinové operace sjednocení, průniku, rozdílu a symetrické diference
7. Implementace pomocí hešovací tabulky
8. Implementace pomocí B-stromu
10. Vytvoření množiny z vektoru
11. Funkce pro vytvoření množiny z vektoru
12. Použití generické formy funkce vec2set
13. Repositář s demonstračními příklady
1. Datové kolekce v programovacím jazyku Rust: množiny
Třetí důležitou datovou strukturou patřící mezi standardní kolekce, se kterou se dříve či později musí seznámit prakticky jakýkoli vývojář používající programovací jazyk Rust, jsou množiny (sets). Ty jsou charakteristické tím, že každý prvek obsahují maximálně jednou (na rozdíl od seznamů, vektorů či hodnot uložených do map). Podobně jako mapy, i množiny existují ve dvou podobách: s nesetříděnými prvky (založeno na hešovacích tabulkách) a se setříděnými prvky (založeno na B-stromech). Pro vytvoření prvního typu množiny je nutno použít typ std::collections::HashSet. Pro vytvoření druhého typu množiny se používá datový typ std::collections::BTreeSet. V obou případech je samozřejmě nutné na začátku modulu použít příkaz use, tedy například:
use std::collections::HashSet;
či:
use std::collections::BTreeSet;
2. Základní operace, které lze provádět s množinami
Nejdůležitějšími množinovými operacemi je sjednocení, průnik, rozdíl (viz též navazující kapitoly) a test, zda je jedna množina podmnožinou (subset) či nadmnožinou jiné množiny. V programovacím jazyku Rust je ovšem množiny možné využít podobně jako další typy sekvencí, tj. získat iterátor atd. Proto se také v případě potřeby práce se setříděnou sekvencí většinou používají právě množiny a nikoli ručně tříděné vektory či pole.
Základní operace s prvky množin:
Operace | Metoda |
---|---|
Vložení prvku | insert() |
Odstranění prvku | remove() |
Přečtení prvku | get() |
Kombinace odstranění a vložení | replace() |
Základní operace s celými množinami:
Operace | Funkce či metoda | Operátor |
---|---|---|
Vytvoření množiny | HashSet::new(), BTreeSet::new() | |
Získání iterátoru | iter() | &množina |
Sjednocení množin | union() | | |
Průnik množin | intesection() | & |
Rozdíl množin | difference() | – |
Symetrická diference | symmetric_difference() | ^ |
Povšimněte si, že pro základní operace s celými množinami byly přetíženy i operátory &, |, – a ^. Podrobnosti si řekneme později.
3. Vytvoření množiny implementované hešovací tabulkou
V prvním demonstračním příkladu si ukážeme vytvoření množiny, která je interně implementována formou hešovací tabulky. Do množiny je vloženo sedm prvků, ovšem dva vkládané prvky mají stejnou hodnotu. Při vkládání prvků se pro otestování unikátnosti prvků v množině používá trait Eq, což mimochodem znamená, že tento trait musí být implementován i datovým typem prvků ukládaných do množiny. Vzhledem k tomu, že trait Eq je pro typ &str korektně implementován, bude ve skutečnosti do množiny vloženo jen šest prvků:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn main() { let mut set = HashSet::new(); set.insert("podporucik"); set.insert("inspektor"); set.insert("praktikant"); set.insert("tovarnik"); set.insert("tovarnik"); set.insert("stevard"); set.insert("podkoni"); print_hashset(&set); }
Povšimněte si že:
- Typ prvků množiny je odvozen překladačem automaticky.
- Proměnná set musí být měnitelná.
- Při výpisu všech prvků se iterátor získává unárním operátorem &
- Pokud budete chtít specifikovat typ množiny, stačí za jméno proměnné zapsat :HashSet<&str>
Po překladu a spuštění se na standardním výstupu objeví je šestice řádků:
stevard inspektor podkoni praktikant podporucik tovarnik
4. Vytvoření množiny implementované B-stromem
Druhý příklad se prakticky neliší od příkladu prvního, pouze se použije odlišná implementace množiny. Ve chvíli, kdy je množina interně implementována B-stromem, budou prvky automaticky při vkládání do množiny zatříděny takovým způsobem, že standardní iterátor vrátí prvky setříděné. Při zatřiďování prvků se používá trait Ord, což opět znamená, že tento trait musí být implementován datovým typem prvků množiny (to je pochopitelně kontrolováno překladačem):
use std::collections::BTreeSet; fn print_hashset(set: &BTreeSet<&str>) { for item in set { println!("{}", item); } } fn main() { let mut set = BTreeSet::new(); set.insert("podporucik"); set.insert("inspektor"); set.insert("praktikant"); set.insert("tovarnik"); set.insert("tovarnik"); set.insert("stevard"); set.insert("podkoni"); print_hashset(&set); }
Po překladu a spuštění se na standardním výstupu objeví jen šestice řádků:
inspektor podkoni podporucik praktikant stevard tovarnik
5. Operace insert() a remove()
Opakem operace insert, která vkládá nové prvky do množiny, je samozřejmě operace remove. Současně tato funkce vrací pravdivostní hodnotu true, pokud odstraňovaný prvek skutečně v množině existoval. Pokud neexistoval, vrátí se hodnota false, ale z pohledu operací prováděných nad množinami se nejedná o chybu:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn main() { let mut set = HashSet::new(); set.insert("podporucik"); set.insert("inspektor"); set.insert("praktikant"); set.insert("tovarnik"); set.insert("tovarnik"); set.insert("stevard"); set.insert("podkoni"); print_hashset(&set); println!("-------------------------------"); set.remove("tovarnik"); set.remove("neco jineho"); print_hashset(&set); }
Příklad výstupu. Před oddělovačem je zobrazen původní obsah množiny, pod oddělovačem pak nový obsah po odstranění jednoho jejího prvku (druhé volání remove pouze vrátilo false):
stevard tovarnik praktikant podkoni inspektor podporucik ------------------------------- stevard praktikant podkoni inspektor podporucik
6. Množinové operace sjednocení, průniku, rozdílu a symetrické diference
Již ve druhé kapitole jsme si řekli, že množiny ze standardní knihovny programovacího jazyka Rust podporují čtyři základní množinové operace s výjimkou doplňku (ten není podporován, protože by v naprosté většině případů musel vygenerovat nekonečnou množinu). Podle očekávání jsou všechny operace reprezentovány metodami, jejichž parametrem je reference na druhou množinu a výsledkem iterátor pro prvky množiny nové. Kromě toho je ovšem možné použít i přetížené operátory, jejichž operandy jsou vždy reference na obě množiny. Použití přetížených operátorů je podle mého názoru v tomto případě mnohem čitelnější:
Operace | Funkce či metoda | Operátor |
---|---|---|
Sjednocení množin | union() | | |
Průnik množin | intesection() | & |
Rozdíl množin | difference() | – |
Symetrická diference | symmetric_difference() | ^ |
7. Implementace pomocí hešovací tabulky
V dalším příkladu jsou všechny čtyři podporované množinové operace volány formou metod:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn main() { let mut set1 = HashSet::new(); let mut set2 = HashSet::new(); set1.insert("podporucik"); set1.insert("inspektor"); set1.insert("praktikant"); set1.insert("tovarnik"); set2.insert("tovarnik"); set2.insert("stevard"); set2.insert("podkoni"); set2.insert("inspektor"); println!("Set1"); print_hashset(&set1); println!("\nSet2"); print_hashset(&set2); println!("\nUnion"); for item in set1.union(&set2) { println!("{}", item); } println!("\nIntersetion"); for item in set1.intersection(&set2) { println!("{}", item); } println!("\nDifference set1-set2"); for item in set1.difference(&set2) { println!("{}", item); } println!("\nDifference set2-set1"); for item in set2.difference(&set1) { println!("{}", item); } println!("\nSymmetric difference"); for item in set1.symmetric_difference(&set2) { println!("{}", item); } }
Příklad výstupu:
Set1 inspektor tovarnik podporucik praktikant Set2 inspektor podkoni tovarnik stevard Union inspektor tovarnik podporucik praktikant podkoni stevard Intersetion inspektor tovarnik Difference set1-set2 podporucik praktikant Difference set2-set1 podkoni stevard Symmetric difference podporucik praktikant podkoni stevard
Přepišme si nyní příklad tak, aby se namísto metod použily přetížené operátory:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn main() { let set1 = ["podporucik", "inspektor", "praktikant", "tovarnik"].iter().cloned().collect(); let set2 = ["tovarnik", "stevard", "podkoni", "inspektor"].iter().cloned().collect(); println!("Set1"); print_hashset(&set1); println!("\nSet2"); print_hashset(&set2); println!("\nUnion"); for item in &set1 | &set2 { println!("{}", item); } println!("\nIntersetion"); for item in &set1 & &set2 { println!("{}", item); } println!("\nDifference set1-set2"); for item in &set1 - &set2 { println!("{}", item); } println!("\nDifference set2-set1"); for item in &set2 - &set1 { println!("{}", item); } println!("\nSymmetric difference"); for item in &set1 ^ &set2 { println!("{}", item); } }
Příklad výstupu:
Set1 inspektor praktikant tovarnik podporucik Set2 stevard inspektor podkoni tovarnik Union inspektor stevard podkoni praktikant tovarnik podporucik Intersetion inspektor tovarnik Difference set1-set2 praktikant podporucik Difference set2-set1 stevard podkoni Symmetric difference stevard podkoni praktikant podporucik
8. Implementace pomocí B-stromu
Pokud kód z předchozího příkladu použijeme, ovšem pro množiny založené na B-stromech, měly by iterátory vrácené metodami union(), intersection(), difference() a symmetric_difference() vracet prvky v setříděném pořadí:
use std::collections::BTreeSet; fn print_btree_set(set: &BTreeSet<&str>) { for item in set { println!("{}", item); } } fn main() { let mut set1 = BTreeSet::new(); let mut set2 = BTreeSet::new(); set1.insert("podporucik"); set1.insert("inspektor"); set1.insert("praktikant"); set1.insert("tovarnik"); set2.insert("tovarnik"); set2.insert("stevard"); set2.insert("podkoni"); set2.insert("inspektor"); println!("Set1"); print_btree_set(&set1); println!("\nSet2"); print_btree_set(&set2); println!("\nUnion"); for item in set1.union(&set2) { println!("{}", item); } println!("\nIntersetion"); for item in set1.intersection(&set2) { println!("{}", item); } println!("\nDifference set1-set2"); for item in set1.difference(&set2) { println!("{}", item); } println!("\nDifference set2-set1"); for item in set2.difference(&set1) { println!("{}", item); } println!("\nSymmetric difference"); for item in set1.symmetric_difference(&set2) { println!("{}", item); } }
Z výstupu je patrné, že skutečně došlo ke správnému zatřídění prvků:
Set1 inspektor podporucik praktikant tovarnik Set2 inspektor podkoni stevard tovarnik Union inspektor podkoni podporucik praktikant stevard tovarnik Intersetion inspektor tovarnik Difference set1-set2 podporucik praktikant Difference set2-set1 podkoni stevard Symmetric difference podkoni podporucik praktikant stevard
9. Vytvoření množiny z pole
Poměrně často se setkáme s potřebou vytvořit neměnitelnou množinu. Vzhledem k tomu, že pro množiny neexistuje vhodná syntaxe konstruktoru, musíme si vypomoci jiným způsobem, například využitím iterátoru vytvořeného pro všechny prvky pole. Následující kód získá iterátor pro dané pole, postupně vytvoří klony jeho prvků a následně z iterátoru vytvoří kolekci. Povšimněte si toho, že samotná proměnná držící množinu již nemusí být měnitelná:
let množina = [].iter().cloned().collect();
Vytvoření množiny z pole lze do zdrojového kódu zařadit velmi snadno:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn main() { let set1 = ["podporucik", "inspektor", "praktikant", "tovarnik"].iter().cloned().collect(); let set2 = ["tovarnik", "stevard", "podkoni", "inspektor"].iter().cloned().collect(); println!("Set1"); print_hashset(&set1); println!("\nSet2"); print_hashset(&set2); println!("\nUnion"); for item in set1.union(&set2) { println!("{}", item); } println!("\nIntersetion"); for item in set1.intersection(&set2) { println!("{}", item); } println!("\nDifference set1-set2"); for item in set1.difference(&set2) { println!("{}", item); } println!("\nDifference set2-set1"); for item in set2.difference(&set1) { println!("{}", item); } println!("\nSymmetric difference"); for item in set1.symmetric_difference(&set2) { println!("{}", item); } }
Poznámka: vyzkoušejte si, co se stane, když bude pole obsahovat shodné prvky.
10. Vytvoření množiny z vektoru
Prakticky stejným způsobem se množina vytváří z vektoru, v tomto případě ale bude překladač vyžadovat přesné určení typu množiny:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn main() { let set1: HashSet<&str> = vec!["podporucik", "inspektor", "praktikant", "tovarnik"].iter().cloned().collect(); let set2: HashSet<&str> = vec!["tovarnik", "stevard", "podkoni", "inspektor"].iter().cloned().collect(); println!("Set1"); print_hashset(&set1); println!("\nSet2"); print_hashset(&set2); println!("\nUnion"); for item in set1.union(&set2) { println!("{}", item); } println!("\nIntersetion"); for item in set1.intersection(&set2) { println!("{}", item); } println!("\nDifference set1-set2"); for item in set1.difference(&set2) { println!("{}", item); } println!("\nDifference set2-set1"); for item in set2.difference(&set1) { println!("{}", item); } println!("\nSymmetric difference"); for item in set1.symmetric_difference(&set2) { println!("{}", item); } }
Poznámka: opět si vyzkoušejte, co se stane, když bude vektor obsahovat shodné prvky.
11. Funkce pro vytvoření množiny z vektoru
V rámci tréningu si můžeme vyzkoušet vytvořit funkci, která převede prvky vektoru na množinu. Tato funkce bude obsahovat jediný výraz, jehož výsledek se bude vracet, takže existují dvě formy zápisu, přičemž je doporučeno použít druhý způsob (ten neobsahuje středník za výrazem):
fn vec2set(v: Vec<&str>) -> HashSet<&str> { return v.iter().cloned().collect(); }
fn vec2set(v: Vec<&str>) -> HashSet<&str> { v.iter().cloned().collect() }
Zařazení této funkce do zdrojového kódu programu je snadné:
use std::collections::HashSet; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn vec2set(v: Vec<&str>) -> HashSet<&str> { v.iter().cloned().collect() } fn main() { let set1 = vec2set(vec!["podporucik", "inspektor", "praktikant", "tovarnik"]); let set2 = vec2set(vec!["tovarnik", "stevard", "podkoni", "inspektor"]); println!("Set1"); print_hashset(&set1); println!("\nSet2"); print_hashset(&set2); println!("\nUnion"); for item in set1.union(&set2) { println!("{}", item); } println!("\nIntersetion"); for item in set1.intersection(&set2) { println!("{}", item); } println!("\nDifference set1-set2"); for item in set1.difference(&set2) { println!("{}", item); } println!("\nDifference set2-set1"); for item in set2.difference(&set1) { println!("{}", item); } println!("\nSymmetric difference"); for item in set1.symmetric_difference(&set2) { println!("{}", item); } }
12. Použití generické formy funkce vec2set
Ve skutečnosti není funkce vec2set popsaná v předchozí kapitole univerzální, protože bude pracovat pouze pro vektory obsahující řetězce. V případě, že budeme chtít vytvořit univerzální funkci, je nutné (asi podle očekávání) použít generické typy, v nichž překladači Rustu zaručíme, že se tato funkce bude volat pouze pro vektory, jejichž prvky implementují traity Copy, Eq a Hash. První z těchto traitů je nutný pro volání cloned(), další dva pro přidání prvků do množiny. Traity se v tomto případě oddělují znakem +:
fn vec2set<T: Copy + Eq + Hash>(v: Vec<T>) -> HashSet<T> { v.iter().cloned().collect() }
Úplný zdrojový kód může vypadat následovně:
use std::collections::HashSet; use std::hash::Hash; fn print_hashset(set: &HashSet<&str>) { for item in set { println!("{}", item); } } fn vec2set<T: Copy + Eq + Hash>(v: Vec<T>) -> HashSet<T> { v.iter().cloned().collect() } fn main() { let set1 = vec2set(vec!["podporucik", "inspektor", "praktikant", "tovarnik"]); let set2 = vec2set(vec!["tovarnik", "stevard", "podkoni", "inspektor"]); println!("Set1"); print_hashset(&set1); println!("\nSet2"); print_hashset(&set2); println!("\nUnion"); for item in set1.union(&set2) { println!("{}", item); } println!("\nIntersetion"); for item in set1.intersection(&set2) { println!("{}", item); } println!("\nDifference set1-set2"); for item in set1.difference(&set2) { println!("{}", item); } println!("\nDifference set2-set1"); for item in set2.difference(&set1) { println!("{}", item); } println!("\nSymmetric difference"); for item in set1.symmetric_difference(&set2) { println!("{}", item); } }
13. 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ář:
Příklad | Odkaz |
---|---|
266_sequences27.rs | https://github.com/tisnik/presentations/blob/master/rust/266_sequences27.rs |
267_sequences28.rs | https://github.com/tisnik/presentations/blob/master/rust/267_sequences28.rs |
268_sequences29.rs | https://github.com/tisnik/presentations/blob/master/rust/268_sequences29.rs |
269_sequences30.rs | https://github.com/tisnik/presentations/blob/master/rust/269_sequences30.rs |
270_sequences31.rs | https://github.com/tisnik/presentations/blob/master/rust/270_sequences31.rs |
271_sequences32.rs | https://github.com/tisnik/presentations/blob/master/rust/271_sequences32.rs |
272_sequences33.rs | https://github.com/tisnik/presentations/blob/master/rust/272_sequences33.rs |
273_sequences34.rs | https://github.com/tisnik/presentations/blob/master/rust/273_sequences34.rs |
274_sequences35.rs | https://github.com/tisnik/presentations/blob/master/rust/274_sequences35.rs |
275_sequences36.rs | https://github.com/tisnik/presentations/blob/master/rust/275_sequences36.rs |
14. Odkazy na Internetu
- Struct std::collections::HashSet
https://doc.rust-lang.org/std/collections/struct.HashSet.html - Struct std::collections::BTreeSet
https://doc.rust-lang.org/std/collections/struct.BTreeSet.html - Set (abstract data type)
https://en.wikipedia.org/wiki/Set_%28abstract_data_type%29#Language_support - Associative array
https://en.wikipedia.org/wiki/Associative_array - Hash Table
https://en.wikipedia.org/wiki/Hash_table - B-tree
https://en.wikipedia.org/wiki/B-tree - Pedro Celis: Robin Hood Hashing (naskenované PDF!)
https://cs.uwaterloo.ca/research/tr/1986/CS-86–14.pdf - Robin Hood hashing
http://codecapsule.com/2013/11/11/robin-hood-hashing/ - Robin Hood hashing: backward shift deletion
http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/ - Module std::collections
https://doc.rust-lang.org/std/collections/ - Module std::vec
https://doc.rust-lang.org/nightly/std/vec/index.html - Struct std::collections::VecDeque
https://doc.rust-lang.org/std/collections/struct.VecDeque.html - Struct std::collections::LinkedList
https://doc.rust-lang.org/std/collections/struct.LinkedList.html - Module std::fmt
https://doc.rust-lang.org/std/fmt/ - Macro std::println
https://doc.rust-lang.org/std/macro.println.html - Enum std::result::Result
https://doc.rust-lang.org/std/result/enum.Result.html - Module std::result
https://doc.rust-lang.org/std/result/ - Result
http://rustbyexample.com/std/result.html - Rust stdlib: Option
https://doc.rust-lang.org/std/option/enum.Option.html - Module std::option
https://doc.rust-lang.org/std/option/index.html - Rust by example: option
http://rustbyexample.com/std/option.html - Rust by example: if-let
http://rustbyexample.com/flow_control/if_let.html - Rust by example: while let
http://rustbyexample.com/flow_control/while_let.html - Rust by example: Option<i32>
http://rustbyexample.com/std/option.html - An Overview of Macros in Rust
http://words.steveklabnik.com/an-overview-of-macros-in-rust - A Practical Intro to Macros in Rust 1.0
https://danielkeep.github.io/practical-intro-to-macros.html - The Rust Programming Language: macros
https://doc.rust-lang.org/beta/book/macros.html - Rust by example: 15 macro_rules!
http://rustbyexample.com/macros.html - Primitive Type isize
https://doc.rust-lang.org/nightly/std/primitive.isize.html - Primitive Type usize
https://doc.rust-lang.org/nightly/std/primitive.usize.html - 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