Hlavní navigace

Dyon: spojení předností Rustu a dynamicky typovaných programovacích ja­zyků

Pavel Tišnovský

Dnes se výjimečně nebudeme zabývat samotným Rustem, ale jazykem Dyon s dynamickým typováním, který byl vytvořen speciálně pro rustovský ekosystém a slouží mj. i jako jazyk vhodný pro použití s herním enginem Piston.

Obsah

1. Dyon – spojení předností Rustu a dynamicky typovaných programovacích jazyků

2. Instalace Dyonu s využitím správce projektů Cargo

3. Proměnné

4. Datové typy

5. Ukázka konstruktorů základních datových typů

6. Funkce

7. Funkce s parametry a „matematická notace“

8. Změna parametrů ve volaných funkcích

9. Programové bloky

10. Uzávěry

11. Řídicí (rozhodovací) konstrukce

12. Programové smyčky

13. Zkrácený zápis smyčky: automatické odvození, přes kterou sekvenci se iteruje

14. Zkrácený zápis vnořených smyček

15. Zápis často používaných typů smyček – suma, hledání maxima atd.

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

17. Odkazy na Internetu

1. Dyon – spojení předností Rustu a dynamicky typovaných programovacích jazyků

„If you need OOP patterns, then there is only one solution: Use another language, for example Rust. Dyon is designed for scripting, as in solving problems fast. It is not designed for building abstractions, or proving things through the type system.“

Při vývoji herního enginu Piston vznikl mj. i poměrně zajímavý programovací jazyk nazvaný Dyon (tento název je odvozen od hypotetické částice). Důvodem pro vznik Dyonu byla především snaha o vytvoření flexibilního jazyka pro rustovský ekosystém, v němž by se navíc měly uplatnit ty nejzajímavější koncepty Rustu, především dealokace objektů na základě analýzy jejich viditelnosti/životnosti, nikoli s použitím klasického správce paměti (garbage collectoru). Dyon sice používá dynamické typování, ovšem umožňuje i plnou specifikaci datových typů (například parametrů funkcí) a navíc kontroluje, zda se nemění datový typ hodnot přiřazovaných do jedné proměnné.

Poznámka: Dyon nelze považovat za univerzální programovací jazyk, který má ambice nahradit dnes populární skriptovací jazyky. Skutečně se na něj musíme dívat jako na doplněk k Rustu u těch částí aplikace, kde se nechceme do podrobností zabývat (mnohdy „zapeklitým“) typovým systémem Rustu.

Mj. i díky dobré kooperaci mezi Rustem a Dyonem je dnes možné vyvíjet aplikace používající oba zmíněné jazyky: Rust spíše pro nízkoúrovňové operace popř. pro implementaci základního engine a Dyon ve funkci „lepidla“ komponent. Ostatně podobný koncept dvou jazyků nalezneme i v dalších oblastech, dnes typicky u dvojice C+Python či Java+Groovy, Java+Clojure apod.

Kromě sledování životnosti proměnných najdeme v Dyonu i další koncepty převzaté z Rustu (a někdy i vylepšené). Jedná se například o použití typů Result a Option, pro něž byl navíc vytvořen speciální operátor atd.

2. Instalace Dyonu s využitím správce projektů Cargo

Instalace programovacího jazyka Dyon je pro zkušenější rustovské programátory triviální, protože je tento jazyk dostupný ve formě balíčku spravovaného systémem Cargo. Postačí si tedy vytvořit nový projekt a do něj do sekce se závislostmi přidat jedinou knihovnu.

Prvním krokem je samozřejmě vytvoření projektu:

$ cargo new --bin dyon-hello-world

Dále upravíme projektový soubor přidáním sekce [dependencies]:

[package]
name = "dyon-hello-world"
version = "0.1.0"
authors = ["Pavel Tisnovsky <ptisnovs@redhat.com>"]
 
[dependencies]
dyon = "0.21.0"

Pokud nyní spustíme překlad projektu, stáhnou se všechny potřebné balíčky, na nichž Dyon závisí, a následně se tyto balíčky přeloží:

$ cargo build
    Updating registry `https://github.com/rust-lang/crates.io-index`
 Downloading dyon v0.21.1
 Downloading piston_meta v0.29.1
 Downloading rand v0.3.16
 Downloading range v0.3.1
 Downloading read_color v0.1.0
 Downloading read_token v0.9.0
 Downloading hyper v0.9.18
 Downloading libc v0.2.29
 Downloading log v0.3.8
 Downloading rustc-serialize v0.3.24
 Downloading unicase v1.4.2
 Downloading httparse v1.2.3
 Downloading num_cpus v1.6.2
 Downloading language-tags v0.2.2
 Downloading url v1.5.1
 Downloading traitobject v0.0.1
 Downloading typeable v0.1.2
 Downloading time v0.1.38
 Downloading cookie v0.2.5
 Downloading solicit v0.4.4
 Downloading mime v0.2.6
 Downloading version_check v0.1.3
 Downloading percent-encoding v1.0.0
 Downloading idna v0.1.4
 Downloading unicode-bidi v0.3.4
 Downloading hpack v0.2.0
   Compiling matches v0.1.6
   Compiling lazy_static v0.2.8
   Compiling range v0.3.1
   Compiling libc v0.2.29
   Compiling typeable v0.1.2
   Compiling read_color v0.1.0
   Compiling unicode-normalization v0.1.5
   Compiling language-tags v0.2.2
   Compiling log v0.3.8
   Compiling httparse v1.2.3
   Compiling version_check v0.1.3
   Compiling rustc-serialize v0.3.24
   Compiling percent-encoding v1.0.0
   Compiling traitobject v0.0.1
   Compiling unicode-bidi v0.3.4
   Compiling read_token v0.9.0
   Compiling time v0.1.38
   Compiling num_cpus v1.6.2
   Compiling rand v0.3.16
   Compiling mime v0.2.6
   Compiling hpack v0.2.0
   Compiling unicase v1.4.2
   Compiling piston_meta v0.29.1
   Compiling idna v0.1.4
   Compiling solicit v0.4.4
   Compiling url v1.5.1
   Compiling cookie v0.2.5
   Compiling hyper v0.9.18
   Compiling dyon v0.21.1
   Compiling dyon-project v0.1.0 (file:///home/tester/rust/projects/dyon-project)
    Finished dev [unoptimized + debuginfo] target(s) in 64.83 secs

Do souboru main.rs přidáme kód pro spuštění nového skriptu napsaného v jazyce Dyon:

extern crate dyon;
 
use dyon::{error, run};
 
fn main() {
    error(run("src/main.dyon"));
}

Vytvoříme zmíněný skript main.dyon, který je prozatím velmi jednoduchý:

fn main() {
    println("Hello world!")
}

Celou aplikaci by nyní mělo být možné přeložit a spustit:

$ cargo run
   Compiling dyon-project v0.1.0 (file:///home/tester/temp/presentations/rust/projects/dyon-project)
    Finished dev [unoptimized + debuginfo] target(s) in 2.9 secs
     Running `target/debug/dyon-project`
Hello world!

3. Proměnné

Proměnné se v Dyonu vytváří velmi jednoduše, dokonce ještě jednodušeji než v Rustu. Celá deklarace proměnné spočívá v uvedení jejího názvu, znaků := pro přiřazení a hodnoty, která se má do proměnné přiřadit. Hodnota je samozřejmě nějakého typu, ze kterého je automaticky odvozen i typ výsledné proměnné:

x := 42

Obsah proměnných je možné měnit, což znamená, že proměnné nejsou ve výchozím nastavení neměnitelné (immutable). Pro změnu obsahu proměnné se používá odlišný znak přiřazení =, nikoli :=. Díky této maličkosti je možné detekovat chyby způsobené překlepem ve jménu proměnné:

x = 0

Při přiřazování hodnot do proměnných se provádí kontroly, zda proměnná již existuje (tj. zda byla deklarována) a současně zda má nová hodnota typ shodný s typem proměnné. To je jeden z podstatných rozdílů oproti dalším dynamicky typovaným jazykům, u nichž je většinou možné do proměnných přiřazovat hodnoty různých typů. Příkladem může být dynamicky typovaný Python:

x=True
x=42
x="xyzzy"
x=(1,2,3)

Mezi chybné zápisy patří:

b = 42

Chyba:

 --- ERROR ---
In `src/main.dyon`:
 
Could not find declaration of `b`
3,5:     b = 42
3,5:     ^

Dále pak pokus o přiřazení hodnoty jiného typu:

a := 42
a = "xyzzy"

Chyba:

 --- ERROR ---
main (src/main.dyon)
variables (src/main.dyon)
 
Expected assigning to text
3,5:     a = "xyzzy"
3,5:     ^

Naproti tomu lze vytvořit novou proměnnou stejného jména, ta ovlivní viditelnost a životnost původní proměnné:

a := 42
a := "xyzzy"

4. Datové typy

V jazyku Dyon nalezneme poměrně velké množství datových typů, zejména:

  • Logické hodnoty true a false reprezentované typem bool.
  • Čísla, která interně odpovídají typu f64 z Rustu. Při zápisu je možné oddělovat tisíce, miliony atd. podtržítkem, což zvyšuje čitelnost.
  • Řetězce, které odpovídají typu str, tj. používá se kódování UTF-8 atd.
  • Heterogenní pole s prvky zapisovanými do hranatých závorek [].
  • Seznamy (links), což jsou v podstatě homogenní pole alokovaná po blocích o velikosti 1 kB. K prvkům seznamů se přistupuje funkcemi head a tail.
  • Čtyřrozměrné vektory, kde ovšem třetí a čtvrtá složka mohou být implicitně nulové, takže je lze použít i jako 2D a 3D vektory. Důvod použití: prakticky všechny grafické algoritmy. Prvky vektorů se zapisují do kulatých závorek.
  • Objekty (objects), ve skutečnosti se ale jedná o slovníky.
  • Uzávěry (closures), o nichž se zmíníme dále.
  • Typ Option známý z Rustu.
  • Typ Result známý opět z Rustu.

5. Ukázka konstruktorů základních datových typů

Podívejme se na příklad, který osvětlí použití (především konstrukci) základních datových typů:

a := true
println(a)
 
b := 42
println(b)
 
c := 1_000_000
println(c)
 
// 4D vektor
d := (1,2,3,4)
println(d)
 
// 3D vektor
e := (1,2,3)
println(e)
 
// 2D vektor
f := (1,2)
println(f)
 
// skalár! (jen umístěný do závorek)
g := (1)
println(g)
 
// heterogenní pole
h := [1,2,3,4,true,"xyzzy"]
println(h)
 
// seznam
i := link{1 2 3 4}
println(i)
println(head(i))
println(tail(i))
println(head(tail(i)))
println(tail(tail(i)))
 
s := "Hello"
println(s)

Výsledky:

true
42
1000000
(1, 2, 3, 4)
(1, 2, 3)
(1, 2)
1
[1, 2, 3, 4, true, "xyzzy"]
1234
some(1)
234
some(2)
34
Hello

Poznámka: prvky seznamů jsou tisknuty za sebou bez mezer.

6. Funkce

Programovací jazyk Dyon má – ostatně podobně jako samotný Rust – některé funkcionální rysy, takže nás pravděpodobně asi nepřekvapí, že se v tomto jazyce velmi dobře a snadno pracuje s funkcemi, navíc je hlídáno správné použití návratových hodnot funkcí apod. Funkce se mohou deklarovat několika způsoby, přičemž základní způsob se v mnoha ohledech podobá samotnému Rustu. Funkce bez parametrů, která nevrací žádnou hodnotu (jde tedy vlastně o proceduru a nikoli plnohodnotnou funkci) bude vypadat takto:

fn funkce1() {
    println("funkce1")
}

Pokud chceme vytvořit funkci, která vrací hodnotu, je nutné před blok s tělem zapsat → a současně je nutné ve funkci použít return. Nelze se tedy spolehnout na to, že poslední výraz ve funkci po svém vyhodnocení vytvoří návratovou hodnotu, která se použije automaticky! Současně se musí návratová hodnota funkce „zkonzumovat“. Podívejme se na příklad:

fn funkce2() -> {
    println("funkce2")
    return 42
}
 
fn functions() {
    print(funkce2())
}

Následující úryvky kódu jsou chybné:

fn funkce2() -> {
    println("funkce2")
    42
}

Chyba vypsaná při spuštění – očekává se explicitní vrácení hodnoty:

 --- ERROR ---
In `src/main.dyon`:
 
Type mismatch (#775):
Expected `any`, found `void`
5,1: fn funkce2() -> {
5,1: ^
6,1:     println("funkce2")
7,1:     42
8,1: }
fn funkce2() {
    println("funkce2")
    return 42
}

Chyba vypsaná při spuštění – zde se naopak příkaz return vůbec neočekává:

 --- ERROR ---
In `src/main.dyon`:
 
Type mismatch (#350):
Expected `void`, found `f64`
7,12:     return 42
7,12:            ^
fn funkce2() -> {
    println("funkce2")
    return 42
}
 
fn functions() {
    funkce2()
}

Zde se „nezkonzumovala“ návratová hodnota funkce:

 --- ERROR ---
In `src/main.dyon`:
 
Type mismatch (#1100):
Unused result `any`
12,5:     funkce2()
12,5:     ^

7. Funkce s parametry a „matematická notace“

Funkce s parametry se zapisuje běžným způsobem, přičemž většinou nepotřebujeme explicitně specifikovat typy parametrů:

fn funkce3(x,y) -> {
    return x*y
}
...
...
...
println(funkce3(6,7))

Existuje ovšem i další a podle mého názoru mnohem zajímavější způsob deklarace funkcí, který autor Dyanu nazval „matematická notace“. Zde se vynechává klíčové slovo fn, explicitní zápis → i klíčového slova return a zápis se zjednoduší na jediný řádek:

funkce4(x,y) = x*y

Volání této funkce se již nijak neliší od volání předchozí funkce:

println(funkce4(6,7))

Konstrukci if-else lze použít i ve výrazu, takže můžeme tvořit i složitější one-linery, například:

inv(x) = if x!=0 {1.0/x} else {0}

Příklad volání:

println(inv(0))
0
 
println(inv(2))
0.5

Samozřejmě můžeme použít i rekurzi (v současnosti bez optimalizací):

factorial(n) = if n <= 1 { 1 }
               else {n * factorial(n-1)}

8. Změna parametrů ve volaných funkcích

Funkce mohou měnit hodnoty svých argumentů, ale v tomto případě se jedná o poměrně problematický rys, který musí být explicitně specifikován jak při deklaraci funkce, tak i při jejím volání. Konkrétně to znamená, že u jména argumentu i parametru musí být zapsáno klíčové slovo mut:

fn inc(mut x) {
    x += 1
}
 
x := 1
println(x)
inc(mut x)
println(x)
inc(mut x)
println(x)
 
1
2
3

Použití mut se poměrně striktně hlídá a pokud toto slovo nepoužijeme, dostaneme následující chybové hlášení:

 --- ERROR ---
In `src/main.dyon`:
 
Requires `mut x`
22,5:     x += 1
22,5:     ^

9. Programové bloky

Základním stavebním prvkem všech aplikací naprogramovaných v Dyonu jsou kromě již výše zmíněných funkcí i bloky, které se již z historických důvodů (viz především programovací jazyky B a C) zapisují mezi složené závorky { a }. Ovšem bloky se v Dyonu, podobně jako v Rustu, chovají jako výrazy, přičemž hodnota posledního výrazu v bloku je současně i návratovou hodnotou celého bloku. Připomeňme si, že se v Dyonu nemusí používat středníky, takže zde nenastává stejný problém jako například v samotném Rustu, kde je velký rozdíl mezi ukončením posledního výrazu středníkem a uvedením stejného výrazu, ovšem bez středníku. Podívejme se nyní na použití jednoduchých bloků (s jedním výrazem) i poněkud složitějších bloků, v nichž je uvedeno větší množství výrazů:

fn blocks() {
    u := 42
    println(u)
 
    v := {42}
    println(v)
 
    w := {6*7}
    println(w)
 
    x := {u*v}
    println(x)
 
    y := {
        a := 6
        b := 7
        a*b
    }
    println(y)
 
    z := {
        a := 6
        b := 7
        if a<b {
            a*b
        } else {
            0
        }
    }
    println(z)
}

Výsledky:

42
42
42
1764
42
42

Musíme si však dát pozor na životnost proměnné (viz též další text, kde se budeme touto problematikou zabývat). Následující příklad skončí s chybou, protože se snažíme proměnnou použít mimo oblast její životnosti:

fn blocks_error() {
    x := {
        y := 42
        y
    }
    println(x)
}

Chyba, která nastane při překladu:

 --- ERROR ---
In `src/main.dyon`:
 
`y` does not live long enough
34,10:     x := {
34,10:          ^
35,1:         y := 42
36,1:         y
37,1:     }

Jedno z řešení spočívá v naklonování reference na hodnotu:

fn blocks_clone() {
    x := {
        y := 42
        clone(y)
    }
    println(x)
}

10. Uzávěry

Podobným způsobem jako funkce se zapisují i uzávěry (closures), při jejichž volání se musí použít znak \ (připomínající lambdu):

f := \(x,y) = x*y
println(\f(6,7))

Složitější uzávěr:

fac := \(n) = if n <= 1 { 1 }
              else {n * factorial(n-1)}

Do uzávěru lze přidat hodnotu (nepředávanou parametrem při jeho volání) s použitím grab:

delta := 6
f := \(x) = x * (grab delta)
 
println(\f(7))
 
42

Popravdě: práce s uzávěry není až tak elegantní, jak by tomu mohlo být při použití odlišného způsobu zápisu.

11. Řídicí (rozhodovací) konstrukce

Základní řídicí konstrukcí je v programovacím jazyku Dyon samozřejmě konstrukce typu if-then popř. if-then-else. Ta se zapisuje prakticky stejným způsobem, jaký známe z Rustu, tj. okolo vyhodnocovaného výrazu se nemusí psát kulaté závorky, ovšem všechny příkazy ve větvích then a else naopak musí být uzavřeny do blokových závorek { a }, a to i tehdy, pokud je celý blok tvořen jediným příkazem. Nejjednodušší tvar řídicí konstrukce if-then je následující:

x := 1
 
if x < 0 {
    println("zaporny")
}

Úplný tvar konstrukce if-then-else pak vypadá takto:

x := 1
 
if x < 0 {
    println("zaporny")
} else {
    println("nezaporny")
}

V případě potřeby je možné zřetězit větší množství podmínek za sebe. Používaný způsob zápisu je následující:

x := 1
 
if x < 0 {
    println("zaporny")
} else if x == 0 {
    println("nulovy")
} else {
    println("kladny")
}

Vzhledem k tomu, že blok je považovaný za výraz, který může vracet hodnotu, platí to stejné i pro celou rozhodovací konstrukci if-then, kterou lze použít všude tam, kde je očekávaný výraz:

x := 1
 
println(if x < 0 {"zaporny"} else {"nezaporny"})

Totéž samozřejmě platí i pro úplnou konstrukci if-then-else:

x := 1
 
println(if x < 0 {"zaporny"} else if x == 0 {"nulovy"} else {"kladny"})

Poznámka: vzhledem k tomu, že je možné rozhodovací konstrukci použít ve výrazu, nebylo nutné do Dyonu přidávat podporu pro poněkud méně čitelný ternární operátor ?:.

12. Programové smyčky

Programové smyčky hrají v jazyku Dyon velmi významnou roli, takže jich zde najdeme poměrně velké množství a navíc je speciálně programová smyčka for navržena takovým způsobem, aby ji bylo možné různými způsoby zkracovat. Nicméně začněme tou nejjednodušší smyčkou, která se jmenuje přímočaře loop. Jedná se o nekonečnou smyčku, která neobsahuje žádnou podmínku ani řídicí proměnnou. Jediná možnost, jak tuto smyčku ukončit, spočívá v použití příkazu break, který zde má stejný význam, jako je tomu v dalších programovacích jazycích odvozených od céčka. Podívejme se na typický (školní) příklad smyčky, která na standardní výstup vypíše hodnoty 0 až 10. Tuto smyčku lze realizovat následovně:

x := 0
loop {
    println(x)
    x += 1
    if x > 10 {break}
}

Výstup:

0
1
2
3
4
5
6
7
8
9
10

V Dyonu nalezneme i počítanou smyčku typu for, kterou lze použít různými způsoby. Podporována je především sémantika podobná céčku (či Javě), kdy se vytvoří (deklaruje) řídicí proměnná smyčky, dále se specifikuje podmínka pro ukončení smyčky a taktéž iterační příkaz provedený vždy na konci každé iterace. Jednotlivé výrazy (deklarace, podmínka, iterační příkaz) se od sebe oddělují středníkem a tělo smyčky je umístěno do bloku ohraničeného závorkami { a }:

for x := 1; x < 1000; x *= 2 {
    println(x)
}

Tato smyčka vypíše mocniny dvou:

1
2
4
8
16
32
64
128
256
512

V mnoha případech se smyčka for používá pro vytvoření posloupnosti celých čísel. Samozřejmě je možné použít zápis:

for i := 0; i < 10; i += 1 {
    println(i)
}

Ovšem to je zbytečně zdlouhavé a především se v množství kódu ztrácí původní idea. Z tohoto důvodu se dá v jazyku Dyon použít zkrácený zápis, kdy se uvede jen horní mez posloupnosti. Řídicí proměnná v takovém případě nabývá hodnot 0, 1, 2 … mez-1:

for i 10 {
    println(i)
}

Výstup:

0
1
2
3
4
5
6
7
8
9

Pokud je zapotřebí, aby posloupnost nezačínala nulou, používá se v programovacích jazycích dosti neobvyklý zápis, který ale připomíná matematický zápis intervalu. Povšimněte si, že první závorka je hranatá a druhá kulatá (v matematice se při zápisu intervalu používají úhlové a kulaté závorky):

for i [10,20) {
    println(i)
}

Výstupem bude v tomto případě řada celých čísel od 10 (včetně) do 20 (kromě):

10
11
12
13
14
15
16
17
18
19

13. Zkrácený zápis smyčky: automatické odvození, přes kterou sekvenci se iteruje

U těch programových smyček, v nichž se prochází polem (ovšem nikoli již vektorem nebo seznamem!) je možné použít zkrácený zápis, v němž se uvede pouze jméno řídicí proměnné a nikoli již požadovaný rozsah hodnot. Ten je automaticky zjištěn z těla smyčky podle toho, jak se řídicí proměnná používá. Zpočátku to může vypadat „magicky“, ovšem ve skutečnosti se jedná o užitečnou vlastnost.

V následujícím zápisu je automaticky zjištěno, že i musí nabývat hodnot od 0 do 3:

a := [1,2,3,10]
 
for i {
    println(a[i])
}

Ve složitějším kódu, kde je řídicí proměnná použita pro indexování většího množství polí, se použije velikost prvního pole ve výrazu. To znamená, že následující kód bude funkční a vypíše jen čtyři hodnoty:

a := [1,2,3,10]
 
b := [1,2,3,4,5,6,7,8]
 
for i {
    println(a[i]*b[i])
}
 
 
 
1
4
9
40

Naproti tomu pokud výraz otočíme, dojde k chybě, protože druhé pole ve výrazu je kratší než pole první:

a := [1,2,3,10]
 
b := [1,2,3,4,5,6,7,8]
 
for i {
    println(b[i]*a[i])
}
 
 
 
 --- ERROR ---
main (src/main.dyon)
consise_loops (src/main.dyon)
 
Out of bounds `4`
219,24:         println(b[i]*a[i])
219,24:                        ^

14. Zkrácený zápis vnořených smyček

V případě, že máme vytvořené dvourozměrné pole:

x:= [[1,2,3], [4,5,6], [7,8,9]]

A potřebujeme procházet všemi jeho prvky, je možné použít zkrácený zápis popsaný v předchozí kapitole:

for i {
    for j {
        println(x[i][j])
    }
}

Dyon však umožňuje další zkrácení vnořené smyčky, a to následovně:

for i, j {
    println(x[i][j])
}

Totéž samozřejmě platí pro trojrozměrná, čtyřrozměrná atd. pole:

y:= [[[1,2,3],
      [4,5,6],
      [7,8,9]],
     [[1,0,0],
      [0,1,0],
      [0,0,1]]]
 
for i {
    for j {
        for k {
            println(y[i][j][k])
        }
    }
}

Versus:

y:= [[[1,2,3],
      [4,5,6],
      [7,8,9]],
     [[1,0,0],
      [0,1,0],
      [0,0,1]]]
 
for i, j, k {
    println(y[i][j][k])

15. Zápis často používaných typů smyček – suma, hledání maxima atd.

Pro často používané smyčky, například pro nalezení minima, maxima, výpočet sumy prvků, součet 2D/3D/4D vektorů apod. obsahuje jazyk Dyon specializované konstrukce, především:

Konstrukce Alternativní zápis Význam
min   zjištění minima
max   zjištění maxima
any test, zda je výraz pravdivý alespoň pro jeden prvek
all test, zda je výraz pravdivý pro všechny prvky
sum suma prvků
prod výsledek vynásobení všech prvků

Podívejme se na některé ukázky:

a := [3,2,1,10,1]
 
minimum := min i { a[i] }
println(minimum)
 
maximum := max i { a[i] }
println(maximum)
 
suma := sum i len(a) { a[i] }
println(suma)
 
product := prod i len(a) { a[i] }
println(product)

S výsledky:

1
10
17
60

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

Většina ukázek z předchozích kapitol byla přidána do dvou demonstračních příkladů, které byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/pre­sentations. Demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý repositář (ovšem u projektů je lepší mít celý repositář, abyste nemuseli pracně stahovat všechny potřebné soubory):

17. Odkazy na Internetu

  1. Dyon: tutoriál
    http://www.piston.rs/dyon-tutorial/
  2. Repositář s programovacím jazykem Dyon
    https://github.com/Piston­Developers/dyon
  3. Dyon: A rusty dynamically typed scripting language
    https://rust.libhunt.com/project/dyon
  4. Dyon snippets
    https://github.com/Piston­Developers/dyon_snippets
  5. Scripting without garbage collector
    http://blog.piston.rs/2016/02/21/scrip­ting-without-garbage-collector/
  6. Podpora pro „matematické“ smyčky
    https://github.com/Piston­Developers/dyon/issues/119
  7. Rust-clippy Wiki
    https://github.com/rust-lang-nursery/rust-clippy/wiki
  8. Rust-clippy
    https://rust.libhunt.com/project/rust-clippy
  9. ndarray – dokumentace k modulu
    https://bluss.github.io/rust-ndarray/master/ndarray/index.html
  10. ndarray – Crate
    https://crates.io/crates/ndarray
  11. rustup
    https://www.rustup.rs/
  12. rustup: the Rust toolchain installer (Git repositář + dokumentace)
    https://github.com/rust-lang-nursery/rustup.rs
  13. The Rust FFI Omnibus
    http://jakegoulding.com/rust-ffi-omnibus/
  14. Build Script Support
    http://doc.crates.io/build-script.html
  15. Calling Rust From Python
    https://bheisler.github.i­o/post/calling-rust-in-python/
  16. Calling Rust in Python (komentáře k předchozímu článku)
    https://www.reddit.com/r/rus­t/comments/63iy5a/calling_rus­t_in_python/
  17. CFFI Documentation
    https://cffi.readthedocs.i­o/en/latest/
  18. Build Script Support
    http://doc.crates.io/build-script.html
  19. Creating a shared and static library with the gnu compiler [gcc]
    http://www.adp-gmbh.ch/cpp/gcc/create_lib.html
  20. ctypes — A foreign function library for Python
    https://docs.python.org/2/li­brary/ctypes.html
  21. FFI: Foreign Function Interface
    https://doc.rust-lang.org/book/ffi.html
  22. Primitive Type pointer
    https://doc.rust-lang.org/std/primitive.pointer.html
  23. Cargo: správce projektů a balíčků pro programovací jazyk Rust
    https://mojefedora.cz/cargo-spravce-projektu-a-balicku-pro-programovaci-jazyk-rust/
  24. Network Communication and Serialization in Rust
    https://www.safaribookson­line.com/blog/2014/01/28/net­work-communication-serialization-rust/
  25. Crate bincode
    http://tyoverby.com/binco­de/bincode/index.html
  26. Struct std::fs::File
    https://doc.rust-lang.org/std/fs/struct.File.html
  27. Trait std::io::Seek
    https://doc.rust-lang.org/std/io/trait.Seek.html
  28. Trait std::io::Read
    https://doc.rust-lang.org/std/io/trait.Read.html
  29. Trait std::io::Write
    https://doc.rust-lang.org/std/io/trait.Write.html
  30. Trait std::io::BufRead
    https://doc.rust-lang.org/std/io/trait.BufRead.html
  31. Module std::io::prelude
    https://doc.rust-lang.org/std/io/prelude/index.html
  32. std::net::IpAddr
    https://doc.rust-lang.org/std/net/enum.IpAddr.html
  33. std::net::Ipv4Addr
    https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
  34. std::net::Ipv6Addr
    https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
  35. TcpListener
    https://doc.rust-lang.org/std/net/struct.TcpLis­tener.html
  36. TcpStream
    https://doc.rust-lang.org/std/net/struct.TcpStream.html
  37. Binary heap (Wikipedia)
    https://en.wikipedia.org/wi­ki/Binary_heap
  38. Binární halda (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Bin%C3%A1rn%C3%AD_halda
  39. Halda (datová struktura)
    https://cs.wikipedia.org/wi­ki/Halda_%28datov%C3%A1_struk­tura%29
  40. Struct std::collections::HashSet
    https://doc.rust-lang.org/std/collections/struc­t.HashSet.html
  41. Struct std::collections::BTreeSet
    https://doc.rust-lang.org/std/collections/struc­t.BTreeSet.html
  42. Struct std::collections::BinaryHeap
    https://doc.rust-lang.org/std/collections/struc­t.BinaryHeap.html
  43. Set (abstract data type)
    https://en.wikipedia.org/wi­ki/Set_%28abstract_data_ty­pe%29#Language_support
  44. Associative array
    https://en.wikipedia.org/wi­ki/Associative_array
  45. Hash Table
    https://en.wikipedia.org/wi­ki/Hash_table
  46. B-tree
    https://en.wikipedia.org/wiki/B-tree
  47. Pedro Celis: Robin Hood Hashing (naskenované PDF!)
    https://cs.uwaterloo.ca/re­search/tr/1986/CS-86–14.pdf
  48. Robin Hood hashing
    http://codecapsule.com/2013/11/11/ro­bin-hood-hashing/
  49. Robin Hood hashing: backward shift deletion
    http://codecapsule.com/2013/11/17/ro­bin-hood-hashing-backward-shift-deletion/
  50. Module std::collections
    https://doc.rust-lang.org/std/collections/
  51. Module std::vec
    https://doc.rust-lang.org/nightly/std/vec/index.html
  52. Struct std::collections::VecDeque
    https://doc.rust-lang.org/std/collections/struc­t.VecDeque.html
  53. Struct std::collections::LinkedList
    https://doc.rust-lang.org/std/collections/struc­t.LinkedList.html
  54. Module std::fmt
    https://doc.rust-lang.org/std/fmt/
  55. Macro std::println
    https://doc.rust-lang.org/std/macro.println.html
  56. Enum std::result::Result
    https://doc.rust-lang.org/std/result/enum.Result.html
  57. Module std::result
    https://doc.rust-lang.org/std/result/
  58. Result
    http://rustbyexample.com/std/re­sult.html
  59. Rust stdlib: Option
    https://doc.rust-lang.org/std/option/enum.Option.html
  60. Module std::option
    https://doc.rust-lang.org/std/option/index.html
  61. Rust by example: option
    http://rustbyexample.com/std/op­tion.html
  62. Rust by example: if-let
    http://rustbyexample.com/flow_con­trol/if_let.html
  63. Rust by example: while let
    http://rustbyexample.com/flow_con­trol/while_let.html
  64. Rust by example: Option<i32>
    http://rustbyexample.com/std/op­tion.html
  65. An Overview of Macros in Rust
    http://words.steveklabnik.com/an-overview-of-macros-in-rust
  66. A Practical Intro to Macros in Rust 1.0
    https://danielkeep.github.io/practical-intro-to-macros.html
  67. The Rust Programming Language: macros
    https://doc.rust-lang.org/beta/book/macros.html
  68. Rust by example: 15 macro_rules!
    http://rustbyexample.com/macros.html
  69. Primitive Type isize
    https://doc.rust-lang.org/nightly/std/primi­tive.isize.html
  70. Primitive Type usize
    https://doc.rust-lang.org/nightly/std/primi­tive.usize.html
  71. Primitive Type array
    https://doc.rust-lang.org/nightly/std/primi­tive.array.html
  72. Module std::slice
    https://doc.rust-lang.org/nightly/std/slice/
  73. Rust by Example: 2.3 Arrays and Slices
    http://rustbyexample.com/pri­mitives/array.html
  74. What is the difference between Slice and Array (stackoverflow)
    http://stackoverflow.com/qu­estions/30794235/what-is-the-difference-between-slice-and-array
  75. Learning Rust With Entirely Too Many Linked Lists
    http://cglab.ca/~abeinges/blah/too-many-lists/book/
  76. Testcase: linked list
    http://rustbyexample.com/cus­tom_types/enum/testcase_lin­ked_list.html
  77. Operators and Overloading
    https://doc.rust-lang.org/book/operators-and-overloading.html
  78. Module std::ops
    https://doc.rust-lang.org/std/ops/index.html
  79. Module std::cmp
    https://doc.rust-lang.org/std/cmp/index.html
  80. Trait std::ops::Add
    https://doc.rust-lang.org/stable/std/ops/trait.Add.html
  81. Trait std::ops::AddAssign
    https://doc.rust-lang.org/std/ops/trait.AddAssign.html
  82. Trait std::ops::Drop
    https://doc.rust-lang.org/std/ops/trait.Drop.html
  83. Trait std::cmp::Eq
    https://doc.rust-lang.org/std/cmp/trait.Eq.html
  84. Struct std::boxed::Box
    https://doc.rust-lang.org/std/boxed/struct.Box.html
  85. Explore the ownership system in Rust
    https://nercury.github.io/rus­t/guide/2015/01/19/ownership­.html
  86. Rust's ownership and move semantic
    http://www.slideshare.net/sa­neyuki/rusts-ownership-and-move-semantics
  87. Trait std::marker::Copy
    https://doc.rust-lang.org/stable/std/marker/tra­it.Copy.html
  88. Trait std::clone::Clone
    https://doc.rust-lang.org/stable/std/clone/tra­it.Clone.html
  89. The Stack and the Heap
    https://doc.rust-lang.org/book/the-stack-and-the-heap.html
  90. Rust Compare: Pointers & References
    http://www.rust-compare.com/site/pointers.html
  91. Rust Compare: Parameters
    http://www.rust-compare.com/site/params.html
  92. Why does this compile? Automatic dereferencing?
    https://users.rust-lang.org/t/why-does-this-compile-automatic-dereferencing/2183
  93. Understanding Pointers, Ownership, and Lifetimes in Rust
    http://koerbitz.me/posts/Understanding-Pointers-Ownership-and-Lifetimes-in-Rust.html
  94. Rust lang series episode #25 — pointers (#rust-series)
    https://steemit.com/rust-series/@jimmco/rust-lang-series-episode-25-pointers-rust-series
  95. Rust – home page
    https://www.rust-lang.org/en-US/
  96. Rust – Frequently Asked Questions
    https://www.rust-lang.org/en-US/faq.html
  97. Destructuring and Pattern Matching
    https://pzol.github.io/get­ting_rusty/posts/20140417_des­tructuring_in_rust/
  98. The Rust Programming Language
    https://doc.rust-lang.org/book/
  99. Rust (programming language)
    https://en.wikipedia.org/wi­ki/Rust_%28programming_lan­guage%29
  100. Go – home page
    https://golang.org/
  101. Stack Overflow – Most Loved, Dreaded, and Wanted language
    https://stackoverflow.com/re­search/developer-survey-2016#technology-most-loved-dreaded-and-wanted
  102. 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/
  103. Rust vs Go: My experience
    https://www.reddit.com/r/go­lang/comments/21m6jq/rust_vs_go_my_ex­perience/
  104. Friends of Rust (Organizations running Rust in production)
    https://www.rust-lang.org/en-US/friends.html
  105. Rust programs versus C++ g++
    https://benchmarksgame.ali­oth.debian.org/u64q/compa­re.php?lang=rust&lang2=gpp
  106. Další benchmarky (nejedná se o reálné příklady „ze života“)
    https://github.com/kostya/benchmarks
  107. Go na Redditu
    https://www.reddit.com/r/golang/
  108. Rust vs. Go
    http://vschart.com/compare/rust/vs/go-language
  109. Abstraction without overhead: traits in Rust
    https://blog.rust-lang.org/2015/05/11/traits.html
  110. Method Syntax
    https://doc.rust-lang.org/book/method-syntax.html
  111. Traits in Rust
    https://doc.rust-lang.org/book/traits.html
  112. Functional Programming in Rust – Part 1 : Function Abstraction
    http://blog.madhukaraphatak­.com/functional-programming-in-rust-part-1/
  113. 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
  114. Chytré ukazatele (moderní verze jazyka C++) [MSDN]
    https://msdn.microsoft.com/cs-cz/library/hh279674.aspx
  115. UTF-8 Everywhere
    http://utf8everywhere.org/
  116. Rust by Example
    http://rustbyexample.com/
  117. Rust oficiálně ve Fedoře
    https://mojefedora.cz/rust-oficialne-ve-fedore/
  118. Resource acquisition is initialization
    https://en.wikipedia.org/wi­ki/Resource_acquisition_is_i­nitialization
  119. TIOBE index (October 2016)
    http://www.tiobe.com/tiobe-index/
  120. 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
  121. String Types in Rust
    http://www.suspectsemantic­s.com/blog/2016/03/27/str­ing-types-in-rust/
  122. Trait (computer programming)
    https://en.wikipedia.org/wi­ki/Trait_%28computer_program­ming%29
  123. Type inference
    https://en.wikipedia.org/wi­ki/Type_inference
Našli jste v článku chybu?