Obsah
1. Operátory v programovacím jazyku OCaml
2. Problematika přetěžování operátorů
3. Definice nových operátorů, další přetížení existujících operátorů
4. Rozdělení programovacích jazyků podle jejich přístupu k operátorům
5. Standardní operátory v OCamlu
6. Unární aritmetické operátory
7. Binární aritmetické operátory
11. Operátory pro spojování řetězců a seznamů
12. Operátory pro čtení a zápis hodnoty přes referenci
13. Ostatní standardní operátory
14. Definice nových operátorů v jazyce OCaml
15. Pravidla pro definici nových operátorů
16. Definice vlastních unárních operátorů
17. Definice vlastních binárních operátorů
18. Asociativita a priorita vlastních operátorů
19. Repositář s demonstračními příklady
1. Operátory v programovacím jazyku OCaml
V předchozím článku o programovacím jazyku OCaml jsme si kromě hlavních témat (jednalo se o datové typy Option, Result a Array) ukázali i způsob definice nového operátoru:
let (>>=) = Result.bind ;;
Operátory hrají v jazycích odvozených od jazyka ML podstatnou roli. Jedná se jak o standardní operátory (v OCamlu jich existuje téměř čtyřicet), tak i o možnost vytvoření operátorů zcela nových, u nichž lze dokonce určit i jejich prioritu a asociativitu. Vlastnosti existujících i nových operátorů budou tématem dnešního článku.
2. Problematika přetěžování operátorů
V mnoha programovacích jazycích se setkáme s takzvanými přetíženými operátory. Jedná se o operátory, jejichž funkce a vlastnosti se mění podle typu operandů. Pravděpodobně nejznámější formou přetížených operátorů jsou operátory určené pro provádění základních aritmetických operací, které bývají definovány pro různé numerické datové typy. Ovšem například operátor + může být přetížen vícekrát, typicky pro operaci spojení řetězců (viz například Java) či například n-tic a seznamů (Python). V těchto případech se nejenom mění funkce operátoru (tj. součet je zcela rozdílná operace od spojení řetězců), ale i jejich další vlastnosti, v tomto případě například komutativita (a nepřímo taktéž asociativita v případě hodnot s plovoucí řádovou čárkou).
V programovacím jazyku OCaml je většina standardních operátorů nepřetížených, což v důsledku znamená, že například aritmetické operace nad celými čísly jsou realizovány odlišnými operátory, než tytéž operace, ovšem na hodnotami s plovoucí řádovou čárkou (v F# je tomu ovšem jinak). Přetížené jsou jen některé operátory, zejména operátory pro porovnání dvou hodnot. Takové operátory akceptují dvojici hodnot se stejným typem, jak si ukážeme dále (a jsou vlastně definovány jako generická funkce).
3. Definice nových operátorů, další přetížení existujících operátorů
Některé programovací jazyky umožňují definici zcela nových operátorů popř. přetížení existujících operátorů. Z tohoto pohledu můžeme programovací jazyky rozdělit do čtyř skupin na základě dvou vlastností (které jsou na sobě nezávislé):
- Lze definovat nové operátory?
- Lze přetížit stávající operátory?
4. Rozdělení programovacích jazyků podle jejich přístupu k operátorům
Zajímavé je, že každá ze čtyř kombinací zmíněných v předchozí kapitole je obsazena nějakým jazykem (a to zcela nezávisle na dalších vlastnostech daného jazyka, tedy nezávisle na typovém systému, podpoře OOP, maker atd.):
Nové operátory nelze přidávat a existující operátory nelze dále přetěžovat
BASIC |
C |
Go |
Java |
JavaScript |
Modula-2 |
Objective-C |
Pascal |
TypeScript |
Visual Basic |
Nové operátory nelze přidávat, ale existující operátory je možné přetěžovat
Ada |
C# |
C++ |
D |
Dart |
FreeBASIC |
Groovy |
Java |
Kotlin |
Lua |
MATLAB |
Object Pascal |
PHP |
Perl |
Python |
Ruby |
Rust |
Visual Basic .NET |
Lze definovat nové operátory, existující operátory ovšem nelze dále přetěžovat
ML |
Pico |
Prolog |
Smalltalk |
Lze definovat nové operátory, navíc je možné přetěžovat existující operátory
ALGOL 68 |
Eiffel |
Fortran |
F# |
Haskell |
Io |
Nim |
R |
Raku |
Scala |
Swift |
5. Standardní operátory v OCamlu
V programovacím jazyce OCaml nalezneme celkem 39 standardních operátorů, tj. operátorů, u kterých je nejenom přesně specifikována prováděná operace, ale taktéž datové typy operandu či (obou) operandů; v závislosti na tom, zda se jedná o unární či o binární operátor. Jedná se o následující operátory:
= <> < > <= >= == != && & || | |> @@ ** ^ + - * / +. -. *. /. ~+ ~- ~+. ~-. @ ! := ^^ mod land lor lxor lsl lsr asr
Jednotlivé operátory z výše uvedeného seznamu budou popsány v navazujících kapitolách.
6. Unární aritmetické operátory
Začneme popisem unárních aritmetických operátorů, protože jejich popis je (alespoň na první pohled) snadný. Unární operátory akceptují jediný operand na pravé straně:
Operátor | Vstupní operand | Výsledek | Popis operátoru |
---|---|---|---|
~- | int | int | unární – (změna znaménka) |
~+ | int | int | unární + |
~-. | float | float | unární – (změna znaménka) |
~+. | float | float | unární + |
Operátor | Vstupní operand | Výsledek | Popis operátoru |
---|---|---|---|
– | int | int | unární – (změna znaménka) |
+ | int | int | unární + |
-. | float | float | unární – (změna znaménka) |
+. | float | float | unární + |
Navíc platí ještě jedna konvence – operátory + a – akceptují i hodnotu typu float a vrací float (takže jsou z tohoto pohledu přetížené, i když to jejich deklarace nenaznačuje.
Podívejme se na několik příkladů:
+42;; - : int = 42 +1.5;; - : float = 1.5 -1.5;; - : float = -1.5 - -42;; - : int = 42 - -1.5;; - : float = 1.5 +.3.14;; - : float = 3.14 -.3.14;; - : float = -3.14 ~-42;; - : int = -42 ~-.3.14;; - : float = -3.14
Deklarace všech čtyř zmíněných operátorů lze získat takto:
(~+) ;; - : int -> int = <fun> (~-) ;; - : int -> int = <fun> (~+.) ;; - : float -> float = <fun> (~-.) ;; - : float -> float = <fun>
7. Binární aritmetické operátory
Následuje poměrně velké množství binárních aritmetických operátorů, které jsou opět rozděleny podle toho, zda jsou definovány pro operandy typu int či float (devátý operátor je definován pouze pro typ float):
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
+ | int | int | součet |
– | int | int | rozdíl |
* | int | int | součin |
/ | int | int | podíl |
mod | int | int | zbytek po celočíselném dělení |
land | int | int | bitový součin |
lor | int | int | bitový součet |
lxor | int | int | bitová nonekvivalence |
lsl | int | int | bitový posun doleva |
lsr | int | int | bitový posun doprava |
asr | int | int | aritmetický posun doprava |
+. | float | float | součet |
-. | float | float | rozdíl |
*. | float | float | součin |
/. | float | float | podíl |
** | float | float | umocnění |
Příklady použití těchto operátorů:
10 + 3;; - : int = 13 10 - 3;; - : int = 7 10 * 3;; - : int = 30 10 / 3;; - : int = 3 10.0 +. 3.0;; - : float = 13. 10.0 -. 3.0;; - : float = 7. 10.0 *. 3.0;; - : float = 30. 10.0 /. 3.0;; - : float = 3.33333333333333348 10.0 ** 3.0;; - : float = 1000.
V OCamlu jsou prováděny striktní typové kontroly:
1 + 2.0;; Line 1, characters 4-7: Error: This expression has type float but an expression was expected of type int 1 +. 2;; Line 1, characters 0-1: Error: This expression has type int but an expression was expected of type float Hint: Did you mean `1.'?
Opět se podívejme na typovou definici všech operátorů. Mezi závorkami a operátorem jsou přidány mezery, protože (* a *) se používá i pro zápis komentářů:
( + ) ;; - : int -> int -> int = <fun> ( - ) ;; - : int -> int -> int = <fun> ( * ) ;; - : int -> int -> int = <fun> ( / ) ;; - : int -> int -> int = <fun> ( +. ) ;; - : float -> float -> float = <fun> ( -. ) ;; - : float -> float -> float = <fun> ( *. ) ;; - : float -> float -> float = <fun> ( /. ) ;; - : float -> float -> float = <fun> ( ** ) ;; - : float -> float -> float = <fun>
8. Booleovské operátory
Tato kapitola bude velmi krátká, protože programátoři mají v jazyce OCaml k dispozici pouze dva standardní booleovské operátory. Jedná se o logický součin a logický součet:
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
&& | bool | bool | logický součin |
|| | bool | bool | logický součet |
Můžete se stále setkat se starším zápisem těchto operátorů pomocí znaků & a |. Ovšem překladač již bude vypisovat varování a znak | nemusí rozpoznat vůbec.
Příklady použití:
false && false ;; - : bool = false false && true ;; - : bool = false true && false ;; - : bool = false true&& true ;; - : bool = true false || false ;; - : bool = false false || true ;; - : bool = true true || false ;; - : bool = true true || true ;; - : bool = true
Typy těchto operátorů opět zjistíme snadno:
( && ) ;; - : bool -> bool -> bool = <fun> ( || ) ;; - : bool -> bool -> bool = <fun> ( & ) ;; Line 1, characters 0-5: 1 | ( & ) ;; ^^^^^ Alert deprecated: Stdlib.& Use (&&) instead. - : bool -> bool -> bool = <fun>
9. Relační operátory
Zajímavé jsou v programovacím jazyce OCaml relační operátory, protože jsou implementovány takovým způsobem, že oba operandy musí být sice stejného typu, ovšem tímto typem mohou být jak číselné hodnoty, tak i řetězce, seznamy, pole atd.
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
< | 'a | bool | test na relaci „menší než“ |
<= | 'a | bool | test na relaci „menší nebo rovno“ |
> | 'a | bool | test na relaci „větší než“ |
>= | 'a | bool | test na relaci „větší nebo rovno“ |
Podívejme se na porovnání numerických hodnot, které je zcela jednoznačné:
1 < 2 ;; - : bool = true 1 > 2 ;; - : bool = false
Řetězce se porovnávají lexikograficky:
"abc" < "zzz" ;; - : bool = true
Nelze se ovšem spoléhat na to, že bude dodržena například česká norma řazení:
a" < "á" ;; - : bool = true "á" < "b" ;; - : bool = false
Zajímavé je, že se dají porovnávat i seznamy. Opět se jedná o lexikografické porovnání s tím, že pokud je relace zaručena pro n-tý prvek, porovnání se v tomto místě zastaví. To je patrné na posledních třech příkladech, kdy postačuje porovnat druhý resp. první prvek:
[1;2;3] < [4;5;6] ;; - : bool = true [1;2;3] < [1;2;3] ;; - : bool = false [1;2;3] < [1;2;4] ;; - : bool = true [1;2;3] < [1;3;3] ;; - : bool = true [1;2;3] < [2;2;3] ;; - : bool = true [1;2;3;4;5;6] < [9] ;; - : bool = true
V případě polí je nutné zaručit jejich shodnou délku:
[|1;2;3|] < [|4;5;6|] ;; - : bool = true [|1;2;3|] < [|1;2;3|] ;; - : bool = false [|1;2;3|] < [|1;3;3|] ;; - : bool = true [|1;2;3|] < [|1;3;0|] ;; - : bool = true [|1;2;3;4;5;6|] < [|9;0;0;0;0;0|] ;; - : bool = true
n-tice se porovnávají prvek po prvku (samozřejmě musí být shodné typy těchto prvků) a opět stačí, aby byla relace splněna pro n-tý prvek, aby byl známý i výsledek operace:
("abc", 1) < ("abc", 2);; - : bool = true ("abc", 1) < ("abc", 0) ;; - : bool = false ("abc", 1) < ("zzz", 1) ;; - : bool = true ("zzz", 1) < ("aaa", 1) ;; - : bool = false
Opět se pro úplnost podívejme na typy všech čtyř výše zmíněných operátorů:
( < ) ;; - : 'a -> 'a -> bool = <fun> ( > ) ;; - : 'a -> 'a -> bool = <fun> ( <= ) ;; - : 'a -> 'a -> bool = <fun> ( >= ) ;; - : 'a -> 'a -> bool = <fun>
10. Testy na ekvivalenci
Samostatná kapitola je vyhrazena pro popis operátorů, které testují ekvivalenci dvou hodnot. Jedná se totiž o poměrně složité téma, které je v mnoha programovacích jazycích realizováno problematickým způsobem (čtyři různé funkce pro ekvivalenci v LISPu eq, eql, equal, equalp, dvojí funkce operátoru == v Javě, dvojice operátorů == a === v JavaScriptu atd.). Můžeme totiž testovat, zda jsou dvě hodnoty totožné z hlediska jejich struktury nebo zda se jedná o totožné objekty uložené ve stejné oblasti paměti.
Z tohoto důvodu nalezneme v jazyku OCaml dva operátory = a ==, jejichž opakem jsou operátory <> a != (pozor si tedy musí dát céčkaři a Javisti na druhý zmíněný operátor). Operátor = testuje strukturální ekvivalenci, tj. zda mají hodnoty stejný typ (to kontroluje překladač) i obsah, zatímco operátor == testuje, zda se jedná o shodné oblasti paměti popř. u číselných hodnot o shodná čísla (ostatní typy jsou totiž boxovány). A ještě problematičtější situace je u měnitelných objektů, kdy tento operátor vrací true za předpokladu, že jedna operace mutace změní obě předávané hodnoty (což musí být pole nebo reference). V praxi se nejčastěji setkáme s použitím = a nikoli ==:
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
= | 'a | bool | strukturální ekvivalence |
<> | 'a | bool | opak = |
== | 'a | bool | fyzická ekvivalence |
!= | 'a | bool | opak == |
Ukažme si použití obou operátorů == a = i rozdílné výsledky, které (někdy) dostaneme:
1 == 1 ;; - : bool = true 1 = 1 ;; - : bool = true [1,2] == [1,2] ;; - : bool = false [1,2] = [1,2] ;; - : bool = true [|1,2|] == [|1,2|] ;; - : bool = false [|1,2|] = [|1,2|] ;; - : bool = true ("foo", 42) == ("foo", 42) ;; - : bool = false ("foo", 42) = ("foo", 42) ;; - : bool = true
Typy výše zmíněných operátorů:
( = ) ;; - : 'a -> 'a -> bool = <fun> ( == ) ;; - : 'a -> 'a -> bool = <fun> ( <> ) ;; - : 'a -> 'a -> bool = <fun> ( != ) ;; - : 'a -> 'a -> bool = <fun>
11. Operátory pro spojování řetězců a seznamů
Další operátory, které v jazyce OCaml nalezneme, slouží ke spojování řetězců nebo seznamů. I když pracují s různými typy, popíšeme si je v jedné kapitole:
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
@ | seznam 'a | seznam 'a | spojení dvou seznamů s prvky stejných typů |
^ | řetězec | řetězec | spojení dvou řetězců |
^^ | formátovací řetězec | formátovací řetězec | spojení dvou formátovacích řetězců |
Formátovací řetězce budou tématem samostatného článku, ovšem podívejme se na způsoby použití operátorů @ a ^. Je to snadné a přímočaré (připomeňme typ prázdného seznamu):
[] @ [] ;; - : 'a list = [] [] @ [1] ;; - : int list = [1] [1] @ [2] ;; - : int list = [1; 2] [1;2] @ [3;4] ;; - : int list = [1; 2; 3; 4] "" ^ "" ;; - : string = "" "" ^ "bar" ;; - : string = "bar" "foo" ^ "" ;; - : string = "foo" "foo" ^ "bar" ;; - : string = "foobar"
Typy těchto operátorů:
( @ ) ;; - : 'a list -> 'a list -> 'a list = <fun> ( ^ ) ;; - : string -> string -> string = <fun> ( ^^) ;; - : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> ('f, 'b, 'c, 'e, 'g, 'h) format6 -> ('a, 'b, 'c, 'd, 'g, 'h) format6 = <fun>
12. Operátory pro čtení a zápis hodnoty přes referenci
Připomeňme si, jak se v jazyku OCaml pracuje s referencemi.
Proměnná obsahující referenci je deklarována s využitím modifikátoru ref:
let x = ref 42
Modifikace referencované hodnoty se provádí s využitím operátoru :=, tedy takto:
x := 0
A pro získání hodnoty se používá operátor !, což je ukázáno na dalším řádku:
Printf.printf "x=%d\n" !x
V tomto popisu jsme použili dva operátory:
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
:= | 'a ref | unit () | nastavení hodnoty přes referenci |
! | 'a ref | 'a | přečtení hodnoty přes referenci |
Typy těchto operátorů si zobrazíme snadno:
( := ) ;; - : 'a ref -> 'a -> unit = <fun> ( ! ) ;; - : 'a ref -> 'a = <fun>
13. Ostatní standardní operátory
Zbývá nám popis pouhých dvou standardních operátorů:
Operátor | Vstupní operandy | Výsledek | Popis operátoru |
---|---|---|---|
@@ | funkce, hodnota | vypočtená hodnota | aplikace funkce |
|> | hodnota, funkce | vypočtená hodnota | aplikace funkce, ovšem funkce se zapisuje za operátor |
Oba výše uvedené operátory jsou vlastně pouze jinak zapsanou formou volání (aplikace) funkce na jednu hodnotu. Oba dále uvedené výrazy vrací 11, tedy totéž, co inc 10;;:
let inc x = x + 1 ;; val inc : int -> int = <fun> inc @@ 10 ;; - : int = 11 10 |> inc ;; - : int = 11
Jak je asi patrné, je praktický především operátor |>, který nám umožňuje tvorbu kolony:
let inc x = x + 1;; let double x = x * 2;; let negate x = -x;; 10 |> inc |> double |> negate;; -22
( @@ ) ;; - : ('a -> 'b) -> 'a -> 'b = <fun> ( |> ) ;; - : 'a -> ('a -> 'b) -> 'b = <fun>
14. Definice nových operátorů v jazyce OCaml
Důležitým rysem programovacího jazyka OCaml je fakt, že je v něm možné vytvářet další operátory. Pro jména těchto operátorů existují pravidla zmíněná v navazující kapitole. Jedná se o poměrně důležitou vlastnost tohoto jazyka, ovšem (pochopitelně) je nutné dát pozor na to, aby byl výsledný program, který nové operátory používá, čitelný. Z hlediska implementace je vhodné si uvědomit, že operátory nejsou v OCamlu vlastně nic jiného než „zajímavým“ způsobem zapsané funkce s jedním či dvěma parametry – nejedná se tedy o žádnou magii. Zajímavé je, že již v názvu nového operátoru je zakódována i jeho asociativita, což si ostatně ukážeme.
15. Pravidla pro definici nových operátorů
Nové operátory se definují stylem:
let (jméno_operátoru) = funkce_s_implementací ;;
Ovšem jména operátorů musí splňovat určitá pravidla. Tato pravidla taktéž určují aritu, prioritu a asociativitu operátoru:
- Prvním znakem prefixového (unárního) operátoru může být ?, ~ nebo !.
- Následovat mohou znaky $, &, *, +, -, /, =, >, @, ^, |, %, < (po znaku ! je následující znak nepovinný).
- Prvním znakem infixového (binárního) operátoru může být $, &, *, +, -, /, =, >, @, ^, |, %, < nebo #.
- Následovat mohou znaky $, &, *, +, -, /, =, >, @, ^, |, %, <, !, ., :, ?, ~,
Současně první znak operátoru určuje jeho prioritu a asociativitu:
Znak | Priorita | Asociativita |
---|---|---|
# | 1 | zleva doprava |
% * / | 2 | zleva doprava |
+ – | 3 | zleva doprava |
@ ^ | 4 | zprava doleva |
$ & < = > | 5 | zleva doprava |
16. Definice vlastních unárních operátorů
Podívejme se nyní na definici jednoduchého binárního operátoru, který bude implementovat operaci logické negace. Pro tento účel můžeme (ideálně jen lokálně) předefinovat existující operátor !, nebo si vytvořit operátor nový. Nazvěme ho například ~/, protože oba tyto znaky se někdy v matematice či elektronice používají pro zápis negace:
let negate x = not x;; let ( ~/ ) = negate;; ~/true;; ~/false;;
Výsledkem obou výrazů s novým operátorem bude skutečně logická negace:
~/true ;; - : bool = false ~/false ;; - : bool = true
Samozřejmě si můžeme vytvořit i další podobné operátory, například operátory (predikáty) testující, zda je celočíselná hodnota kladná, záporná nebo nulová. Pro tyto účely použijeme symboly ?+, ?- a ?=:
let pos x = x > 0;; let neg x = x < 0;; let zero x = x = 0;; let ( ?+ ) = pos;; let ( ?- ) = neg;; let ( ?= ) = zero;; ?+ 42;; ?- 42;; ?= 42;;
Podívejme se na výsledky všech tří výrazů:
+ 42 ;; - : bool = true ?- 42 ;; - : bool = false ?= 42 ;; - : bool = false
17. Definice vlastních binárních operátorů
V praxi bude pravděpodobně zajímavější definice operátorů binárních, protože výše popsané unární operátory jsou vlastně jen „divnými znaky“ zapsaná volání funkcí. U binárních operátorů je tomu ovšem jinak, protože tyto operátory se píšou mezi své operandy a nikoli před nimi. Můžeme si například zadefinovat nový operátor +@, který bude spojovat dvojici řetězců (operandů), ovšem výsledek navíc umístí do hranatých závorek a mezi spojené řetězce přidá znak podtržítka (podobný příklad naleznete i v manuálu k jazyku OCaml):
let strjoin s1 s2 = "[" ^ s1 ^ "_" ^ s2 ^ "]";; let ( +@ ) = strjoin;; "foo" +@ "bar";; "foo" +@ "bar" +@ "baz";;
Z prvního výsledku je patrná základní funkce nového operátoru, z výsledku druhého pak jeho asociativita (zleva):
"foo" +@ "bar";; - : string = "[foo_bar]" "foo" +@ "bar" +@ "baz" ;; - : string = "[[foo_bar]_baz]"
18. Asociativita a priorita vlastních operátorů
V patnácté kapitole byla vypsána pravidla platná pro nově definované operátory. Mj. jsme se v ní zmínili o asociativitě, tedy o tom, zda bude zápis:
x op y op z
vyhodnocen takto:
(x op y) op z
či naopak takto:
x op (y op z)
Náš první binární operátor byl asociativní zleva, ovšem změnou jeho názvu můžeme vytvořit operátor asociativní zprava (viz opět patnáctou kapitolu):
let strjoin s1 s2 = "[" ^ s1 ^ "_" ^ s2 ^ "]";; let ( @@ ) = strjoin;; "foo" @@ "bar";; "foo" @@ "bar" @@ "baz";;
Z druhého výrazu je patrné odlišné „uzávorkování“:
"foo" @@ "bar" ;; - : string = "[foo_bar]" "foo" @@ "bar" @@ "baz" ;; - : string = "[foo_[bar_baz]]"
Podobně je možné volbou jména binárního operátoru určit jeho prioritu, tj. do které z pěti skupin bude operátor spadat. Pro jednoduchost použijeme vlastní operátory začínající znaky + a *, protože jejich vzájemná priorita bude stejná, jako je tomu v matematice. Oba operátory budou provádět stejnou operaci, ovšem vyhodnocení výrazu bude prioritou ovlivněno:
let strjoin s1 s2 = "[" ^ s1 ^ "_" ^ s2 ^ "]";; let ( +@ ) = strjoin;; let ( *@ ) = strjoin;; "foo" +@ "bar" +@ "baz";; "foo" *@ "bar" *@ "baz";; "foo" +@ "bar" *@ "baz";; "foo" *@ "bar" +@ "baz";;
První dva výrazy ukazují, že asociativita obou operátorů je zleva doprava (a nemusíme se jí tedy dále zabývat):
"foo" +@ "bar" +@ "baz" ;; - : string = "[[foo_bar]_baz]" "foo" *@ "bar" *@ "baz" ;; - : string = "[[foo_bar]_baz]"
Ovšem další dva výrazy ukazují, že operátor *@ má vyšší prioritu než operátor +@:
"foo" +@ "bar" *@ "baz" ;; - : string = "[foo_[bar_baz]]" "foo" *@ "bar" +@ "baz" ;; - : string = "[[foo_bar]_baz]"
19. Repositář s demonstračními příklady
Všechny výše popsané demonstrační příklady byly uloženy do repositáře dostupného na adrese https://github.com/tisnik/ocaml-examples/. V tabulce umístěné pod tímto odstavcem jsou uvedeny odkazy na tyto příklady:
20. Odkazy na Internetu
- General-Purpose, Industrial-Strength, Expressive, and Safe
https://ocaml.org/ - OCaml playground
https://ocaml.org/play - Online Ocaml Compiler IDE
https://www.jdoodle.com/compile-ocaml-online/ - Get Started – OCaml
https://www.ocaml.org/docs - Get Up and Running With OCaml
https://www.ocaml.org/docs/up-and-running - Better OCaml (Online prostředí)
https://betterocaml.ml/?version=4.14.0 - OCaml file extensions
https://blog.waleedkhan.name/ocaml-file-extensions/ - First thoughts on Rust vs OCaml
https://blog.darklang.com/first-thoughts-on-rust-vs-ocaml/ - Standard ML of New Jersey
https://www.smlnj.org/ - Programming Languages: Standard ML – 1 (a navazující videa)
https://www.youtube.com/watch?v=2sqjUWGGzTo - 6 Excellent Free Books to Learn Standard ML
https://www.linuxlinks.com/excellent-free-books-learn-standard-ml/ - SOSML: The Online Interpreter for Standard ML
https://sosml.org/ - ML (Computer program language)
https://www.barnesandnoble.com/b/books/other-programming-languages/ml-computer-program-language/_/N-29Z8q8Zvy7 - Strong Typing
https://perl.plover.com/yak/typing/notes.html - What to know before debating type systems
http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html - Types, and Why You Should Care (Youtube)
https://www.youtube.com/watch?v=0arFPIQatCU - DynamicTyping (Martin Fowler)
https://www.martinfowler.com/bliki/DynamicTyping.html - DomainSpecificLanguage (Martin Fowler)
https://www.martinfowler.com/bliki/DomainSpecificLanguage.html - Language Workbenches: The Killer-App for Domain Specific Languages?
https://www.martinfowler.com/articles/languageWorkbench.html - Effective ML (Youtube)
https://www.youtube.com/watch?v=-J8YyfrSwTk - Why OCaml (Youtube)
https://www.youtube.com/watch?v=v1CmGbOGb2I - Try OCaml
https://try.ocaml.pro/ - CSE 341: Functions and patterns
https://courses.cs.washington.edu/courses/cse341/04wi/lectures/03-ml-functions.html - Comparing Objective Caml and Standard ML
http://adam.chlipala.net/mlcomp/ - What are the key differences between Standard ML and OCaml?
https://www.quora.com/What-are-the-key-differences-between-Standard-ML-and-OCaml?share=1 - Cheat Sheets (pro OCaml)
https://www.ocaml.org/docs/cheat_sheets.html - Think OCaml: How to Think Like a (Functional) Programmer
https://www.greenteapress.com/thinkocaml/thinkocaml.pdf - The OCaml Language Cheat Sheet
https://ocamlpro.github.io/ocaml-cheat-sheets/ocaml-lang.pdf - Syllabus (FAS CS51)
https://cs51.io/college/syllabus/ - Abstraction and Design In Computation
http://book.cs51.io/ - Learn X in Y minutes Where X=Standard ML
https://learnxinyminutes.com/docs/standard-ml/ - CSE307 Online – Summer 2018: Principles of Programing Languages course
https://www3.cs.stonybrook.edu/~pfodor/courses/summer/cse307.html - CSE307 Principles of Programming Languages course: SML part 1
https://www.youtube.com/watch?v=p1n0_PsM6hw - CSE 307 – Principles of Programming Languages – SML
https://www3.cs.stonybrook.edu/~pfodor/courses/summer/CSE307/L01_SML.pdf - History of programming languages
https://devskiller.com/history-of-programming-languages/ - History of programming languages (Wikipedia)
https://en.wikipedia.org/wiki/History_of_programming_languages - The Evolution Of Programming Languages
https://www.i-programmer.info/news/98-languages/8809-the-evolution-of-programming-languages.html - Evoluce programovacích jazyků
https://ccrma.stanford.edu/courses/250a-fall-2005/docs/ComputerLanguagesChart.png - Currying
https://sw-samuraj.cz/2011/02/currying/ - Currying (Wikipedia)
https://en.wikipedia.org/wiki/Currying - Currying (Haskell wiki)
https://wiki.haskell.org/Currying - Haskell Curry
https://en.wikipedia.org/wiki/Haskell_Curry - Moses Schönfinkel
https://en.wikipedia.org/wiki/Moses_Sch%C3%B6nfinkel - So You Want to be a Functional Programmer (Part 1)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-1–1f15e387e536 - So You Want to be a Functional Programmer (Part 2)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-2–7005682cec4a - So You Want to be a Functional Programmer (Part 3)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-3–1b0fd14eb1a7 - So You Want to be a Functional Programmer (Part 4)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-4–18fbe3ea9e49 - So You Want to be a Functional Programmer (Part 5)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-5-c70adc9cf56a - So You Want to be a Functional Programmer (Part 6)
https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-6-db502830403 - Python to OCaml: Retrospective
http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-retrospective/ - Why does Cambridge teach OCaml as the first programming language?
https://www.youtube.com/watch?v=6APBx0WsgeQ - OCaml and 7 Things You Need To Know About It In 2021 | Functional Programming | Caml
https://www.youtube.com/watch?v=s0itOsgcf9Q - OCaml 2021 – 25 years of OCaml
https://www.youtube.com/watch?v=-u_zKPXj6mw - Introduction | OCaml Programming | Chapter 1 Video 1
https://www.youtube.com/watch?v=MUcka_SvhLw&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU - Functional Programming – What | OCaml Programming | Chapter 1 Video 2
https://www.youtube.com/watch?v=JTEwC3HihFc&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=2 - Functional Programming – Why Part 1 | OCaml Programming | Chapter 1 Video 3
https://www.youtube.com/watch?v=SKr3ItChPSI&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=3 - Functional Programming – Why Part 2 | OCaml Programming | Chapter 1 Video 4
https://www.youtube.com/watch?v=eNLm5Xbgmd0&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=4 - OCaml | OCaml Programming | Chapter 1 Video 5
https://www.youtube.com/watch?v=T-DIW1dhYzo&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=5 - Five Aspects of Learning a Programming Language | OCaml Programming | Chapter 2 Video 1
https://www.youtube.com/watch?v=A5IHFZtRfBs&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=6 - Expressions | OCaml Programming | Chapter 2 Video 2
https://www.youtube.com/watch?v=3fzrFY-2ZQ8&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=7 - If Expressions | OCaml Programming | Chapter 2 Video 3
https://www.youtube.com/watch?v=XJ6QPtlPD7s&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=8 - Let Definitions | OCaml Programming | Chapter 2 Video 4
https://www.youtube.com/watch?v=eRnG4gwOTlI&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=10 - Let Expressions | OCaml Programming | Chapter 2 Video 5
https://www.youtube.com/watch?v=ug3L97FXC6A&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=10 - Variable Expressions and Scope | OCaml Programming | Chapter 2 Video 6
https://www.youtube.com/watch?v=_TpTC6eo34M&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=11 - Scope and the Toplevel | OCaml Programming | Chapter 2 Video 7
https://www.youtube.com/watch?v=4SqMkUwakEA&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=12 - Anonymous Functions | OCaml Programming | Chapter 2 Video 8
https://www.youtube.com/watch?v=JwoIIrj0bcM&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=13 - Lambdas | OCaml Programming | Chapter 2 Video 9
https://www.youtube.com/watch?v=zHHCD7MOjmw&list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU&index=15 - Operators
https://ocaml.org/docs/operators - Operator overloading
https://en.wikipedia.org/wiki/Operator_overloading