Hlavní navigace

Proměnné, funkce a datové typy v jazyku OCaml

19. 9. 2023
Doba čtení: 19 minut

Sdílet

 Autor: OCaml authors, podle licence: Rights Managed
Na druhý článek o programovacím jazyku F# dnes opět navážeme „doplňujícím“ článkem, v němž si vysvětlíme stejné koncepty, nyní ovšem upravené do takové podoby, aby je bylo možné přímo využít v jazyku OCaml.

Obsah

1. Proměnné, funkce a datové typy v jazyku OCaml

2. Přiřazení hodnot k symbolům

3. Shadowing

4. Neměnitelné hodnoty

5. Reference

6. Použití referencí – jednoduchý čítač

7. Standardní funkce incr

8. Základní datové typy v jazyku OCaml

9. Typ unit

10. Polymorfické funkce

11. n-tice

12. Záznamy

13. Typová inference u záznamů

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

15. Odkazy na Internetu

1. Proměnné, funkce a datové typy v jazyku OCaml

Na druhý článek o programovacím jazyku F# dnes opět navážeme „doplňujícím“ článkem, v němž si vysvětlíme stejné koncepty, nyní ovšem upravené do takové podoby, aby je bylo možné přímo využít v programovacím jazyku OCaml. Vzhledem k tomu, že F# vychází právě z OCamlu, neuvidíme prozatím žádné podstatné rozdíly, ovšem jak bude seriál o F#/Ocamlu pokračovat, postupně uvidíme, že se oba na první pohled prakticky totožné jazyky od sebe odlišují a že (možná poněkud paradoxně) je v některých oblastech OCaml dále, než jazyk F#.

Připomeňme si způsob deklarace neměnitelné (immutable) proměnné, tedy proměnné v původním matematickém slova smyslu:

let x = 42;;

OCaml z tohoto zápisu dokáže odvodit typ proměnné (type inference):

val x : int = 42

Typ proměnné je svázán s její hodnotou i jejím identifikátorem.

Pro tisk hodnoty proměnné (nebo jiného výrazu) na standardní výstup můžeme použít funkci nazvanou Printf.printf, které se předává formátovací řetězec a další hodnota či hodnoty. Oproti jazyku F# je zde tedy navíc specifikace jména modulu Printf:

let x = 42;;
 
Printf.printf "x=%d\n" x;;
Poznámka: počet a typ předávaných hodnot kontroluje překladač!

V REPLu můžeme (alespoň zdánlivě) měnit hodnotu proměnné pomocí deklarace s klíčovým slovem let. Ve skutečnosti však vytvoříme novou proměnnou, která zastíní proměnnou předchozí:

let x = 42;;
Printf.printf "x=%d\n" x;;
 
let x = 6502;;
Printf.printf "x=%d\n" x;;

Jednou deklarované proměnné lze pochopitelně použít i v dalších výrazech:

let x = 42;;
Printf.printf "x=%d\n" x;;
 
let y = x + 1;;
Printf.printf "y=%d\n" y;;
 
let z = y + 1;;
Printf.printf "x=%d\n" z;;

Proměnné, ke kterým se přistupuje, však již musí existovat (neexistuje zde tedy „automagické“ vytvoření proměnné při jejím prvním použití):

let w = neznama;;

Tento nedostatek překladač opět velmi rychle odhalí:

Line 1, characters 8-9:
Error: Unbound value w

2. Přiřazení hodnot k symbolům

Pro deklaraci proměnné (včetně proměnné typu funkce – funkce jsou totiž v OCamlu plnohodnotnými typy) se používá klíčové slovo let, které zajišťuje vazbu (binding) mezi novým symbolem (jménem) a nějakou hodnotou, která je výsledkem nějakého výrazu (a samozřejmě i zde platí, že konstanta je plnohodnotným výrazem). V tom nejjednodušším případě může definice takové vazby vypadat naprosto stejně, jako je tomu v programovacím jazyku F#:

let x = 42

Hodnotu navázanou na symbol pochopitelně můžeme přečíst a nějak ji zpracovat, například vytisknout na terminál:

Printf.printf "x=%d\n" x;;

A můžeme ji použít při definici jiné proměnné:

let y = x + 1
printf "y=%d" y

Na druhou stranu ovšem není možné hodnotu takové proměnné měnit. A podobně jako v programovacím jazyku F#, i v OCamlu znamená symbol = porovnání a nikoli přiřazení, takže se v následujícím příkladu porovnává hodnota x s hodnotou x+1, což znamená, že výsledkem tohoto porovnání bude vždy false:

let x = 42;;
 
Printf.printf "x=%d\n" x;;
 
x = x + 1;;
 
Printf.printf "x=%d\n" x;;

Tento příklad vypíše dvakrát hodnotu 42 a výsledkem výrazu x = x + 1 bude podle očekávání:

- : bool = false

Chování operátoru = si můžeme ověřit na tomto jednoduchém příkladu (povšimněte si, že ve formátovacím řetězci používáme „%b“ a nikoli „%d“, což je opět jazykem kontrolováno):

let x = 42;;
 
Printf.printf "x=%d\n" x;;
 
Printf.printf "x=x+1: %b\n" (x=x+1);;
Printf.printf "x=42:  %b\n" (x=42);;

Výsledky tohoto prográmku jsou předvídatelné:

x=x+1: false
x=42:  true

3. Shadowing

Ve druhém článku o programovacím jazyku F# jsme si taktéž ukázali koncept takzvaného shadowingu, kdy jeden symbol může v nějakém bloku zastínit stejně pojmenovaný symbol z vnějšího bloku. V jazyku F# je umožněn následující zápis, v němž se vrací hodnota vnitřního symbolu a (tedy hodnota 2):

let shadow =
   let a = 1
   let a = 2
   a
 
printf "%d" shadow

V programovacím jazyce OCaml není tento stručný zápis umožněn. Namísto toho je nutné použít klíčové slovo in, které naznačuje, že každý příkaz let ve skutečnosti vytváří nový blok:

let shadow =
   let a = 1 in
   let a = 2 in
   a;;
 
Printf.printf "%d" shadow

Překladač jazyka OCaml navíc ohlásí, že jedna z proměnných a není použita:

1 Warning : unused variable a.

V interaktivním webovém prostředí vypadá toto varování následovně (povšimněte si, jak se proměnná označí):

Obrázek 1: Varování, že v bloku je nevyužitá proměnná.

4. Neměnitelné hodnoty

V jazyku OCaml jsou hodnoty navázané na symboly (neboli proměnné) neměnitelné, stejně jako v programovacím jazyku F#. Ostatně jazyk F# tuto vlastnost z OCamlu převzal, takže se nejedná o žádnou novinku. Pokusme se, naprosto stejně jako v článku o jazyku F#, nadeklarovat proměnnou x, vypsat její hodnotu a následně ji změnit:

let x = 42;;
Printf.printf "x=%d\n" x;;
 
x := x + 1;;
Printf.printf "x=%d\n" x;;

Překladač jazyka OCaml v tomto případě vypíše poněkud kryptické chybové hlášení:

Line 4, characters 0-1:
Error: This expression has type int but an expression was expected of type 'a ref

Toto hlášení oznamuje, že modifikovat lze pouze referencované hodnoty – viz navazující kapitolu.

Poznámka: v jazyku F# je, na rozdíl od OCamlu, možné vytvářet měnitelné proměnné (mutable variables) a proto je zde chybové hlášení pro uživatele jasnější:
This value is not mutable. Consider using the mutable keyword, e.g. 'let
mutable x = expression'.

5. Reference

V programovacím jazyku F# je umožněno vytvářet měnitelné proměnné, a to následujícím zápisem:

let mutable x = 42
printf "x=%d" x
 
x <- x + 1
printf "x=%d" x

Tento zápis a vlastně i celý koncept není v jazyce OCaml umožněn (i když modifikátor mutable zde existuje, ale v jiném kontextu). Namísto měnitelných proměnných se používají referencované hodnoty, zkráceně reference nebo jen refy. Referenci si můžeme představit jako proměnnou obsahující adresu hodnoty uložené v operační paměti. Ovšem na rozdíl od céčka s jeho konceptem ukazatelů jsou ve skutečnosti reference v programovacím jazyku OCaml plně typované.

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 jazyce F# je tomu stejně, ovšem existuje zde navíc možnost použít zápis x.Value.

6. Použití referencí – jednoduchý čítač

Podobně jako v článku o programovacím jazyku F# si nyní vytvořme demonstrační příklad, v němž je reference využita pro realizaci jednoduchého čítače. Bude se tedy jednat o proměnnou, jejíž hodnotu lze zvýšit o jedničku, popř. danou hodnotu přečíst. Víme již, že proměnnou s referencí musíme deklarovat s využitím modifikátoru ref, změnu reference zařizuje operátor := a přečtení referencované hodnoty lze realizovat přes operátor !. Zbytek je již jednoduchý:

let x = ref 42;;
Printf.printf "x=%d\n" !x;;
 
x := !x + 1;;
Printf.printf "x=%d\n" !x;;

Tento prográmek po svém spuštění vypíše:

x=42
x=43
Poznámka: při čtení referencované hodnoty se musí použít operátor !, což je hlídáno překladačem. Pokud zapomeneme:
let x = ref 42;;
Printf.printf "x=%d\n" x;;
 
x := x + 1;;
Printf.printf "x=%d\n" x;;

budeme na tuto chybu upozorněni překladačem:

Line 2, characters 23-24:
Error: This expression has type int ref but an expression was expected of type int

7. Standardní funkce incr

V jazyku OCaml existuje standardní funkce nazvaná incr, která dokáže zvýšit referencovanou celočíselnou hodnotu o jedničku (a současně nevrací žádnou hodnotu, k čemuž se záhy dostaneme). Typ této funkce tedy je:

val incr : int ref -> unit

Použití je snadné:

let x = ref 42;;
Printf.printf "x=%d\n" !x;;
 
incr x;;
Printf.printf "x=%d\n" !x;;
Poznámka: funkci incr se musí předat reference na celé číslo, nikoli samotná celočíselná hodnota. Toto je tedy chybné použití:
let x = 42;;
Printf.printf "x=%d\n" x;;
 
incr x;;
Printf.printf "x=%d\n" x;;

Zde překladač objeví a nahlásí chybu, která je „opačná“, než chyba z předchozí kapitoly:

Line 4, characters 5-6:
Error: This expression has type int but an expression was expected of type int ref

8. Základní datové typy v jazyku OCaml

Základní datové typy dostupné v jazyku OCaml se v několika ohledech odlišují od typů, s nimiž jsme se seznámili při popisu programovacího jazyka F#. Na jednu stranu je například menší nabídka celočíselných datových typů (což lze řešit knihovnami), protože OCaml nemusí spolupracovat s dalšími jazyky v rámci nějakého ekosystému (jak je tomu v ekosystému .NET), na stranu druhou se v OCamlu rozlišuje mezi měnitelnými (bytes) a neměnitelnými (string) řetězci:

Typ Stručný popis Poznámka
bool pravdivostní hodnoty true a false
     
int celá čísla se znaménkem buď 31 bitů nebo 63 bitů (ano, jeden bit je rezervován)
int32 celá čísla se znaménkem uložena v 32 bitech
int64 celá čísla se znaménkem uložena v 64 bitech
     
float hodnoty s plovoucí řádovou čárkou dvojitá přesnost dle IEEE 754
     
char ASCII znak ‚A‘
string neměnitelný řetězec „www.root.cz“
bytes měnitelný řetězec
     
unit typ s jedinou hodnotou () viz navazující kapitolu
list seznam [1;2;3]
array pole [|1;2;3|]
tuple n-tice (1, „foo“, ‚b‘)
Poznámka: povšimněte si, že typ int je buď 31bitový nebo 63bitový, protože jeden bit je použit jako tag pro interní rozlišení mezi celočíselnou hodnotou a ukazatelem na boxovanou hodnotu (například při automatické správě paměti). Jedná se o implementační detail, ale když už na tuto vlastnost upozorňuji: tento bit bývá nejnižší a u celočíselných hodnot je nastaven na jedničku (protože ukazatele jsou zarovnány a tudíž jejich nejnižší bit či bity jsou nulové).

9. Typ unit

I v programovacím jazyce OCaml se setkáme s datovým typem unit, s nímž jsme se seznámili ve druhém článku o programovacím jazyce F#. Připomeňme si jen, že se tato hodnota používá v těch místech, kde je formálně nutné zapsat nějaký typ či hodnotu, ale žádný takový typ ani hodnota nedává smysl. Příkladem je opět funkce incr, která provádí nějakou činnost (zvyšuje hodnotu referencované proměnné), ovšem nic nevrací. A právě návratovým typem takové funkce je (). Tento typ se ovšem odlišuje od void z céčka, k čemuž se ještě vrátíme (ve stručnosti – void není plnohodnotným typem).

Způsob zápisu:

()

Výsledná hodnota a její typ:

- : unit = ()

Podívejme se pro úplnost na rozdíl mezi proměnnou typu unit a funkcí bez parametrů:

let x = ();;
let y () = 42;;

Rozdíl je patrný při vyhodnocování:

y ;;
- : unit -> int = <fun>
 
y() ;;
- : int = 42
 
x ;;
- : unit = ()

10. Polymorfické funkce

Jazyk F# převzal koncept polymorfických funkcí právě z programovacího jazyka OCaml, takže je vhodné se o tomto konceptu ve stručnosti zmínit i dnes. Pro ukázku si nadeklarujeme funkci (pro jednoduchost pojmenovanou ident), která akceptuje nějaký parametr pojmenovaný x a hodnotu tohoto parametru vrátí jako svůj výsledek. U této funkce ovšem nikde nespecifikujeme ani typ parametru ani typ návratové hodnoty:

let ident x = x;;

Typ takové funkce bude označen symbolem 'a:

val ident : 'a -> 'a = <fun>

Značka 'a se původně zapisovala jako α a značí generický typ – funkce tedy akceptuje a vrací libovolnou hodnotu. To ovšem znamená, že můžeme bez problémů psát:

Printf.printf "ident=%d\n" (ident 10);;
Printf.printf "ident=%s\n" (ident "foo");;

Navíc to znamená, že funkci ident můžeme volat i s hodnotou typu unit (tedy jakoby „bez parametrů“). Zápis musí vypadat takto:

ident();;

Výsledkem bude:

- : unit = ()
Poznámka: závorky je nutné uvést, protože samotný výraz ident;; pouze vrátí instanci funkce ident, nikoli výsledek jejího zavolání.

Zkusme si nyní složitější příklad polymorfních funkcí, u nichž překladač nemůže dopředu odvodit jejich typ (a proto dosadí 'a):

let ident x = x;;
 
let first x y = x;;
 
let second x y = y;;
 
let add x y = x + y;;
 
ident (add (first 1 2) (second 1 2));;

Výsledkem bude hodnota 3 s typem int:

- : int = 3

To je ovšem zajímavé, protože typy jednotlivých funkcí jsou:

let ident x = x ;;
val ident : 'a -> 'a = <fun>
 
let first x y = x ;;
val first : 'a -> 'b -> 'a = <fun>
 
let second x y = y ;;
val second : 'a -> 'b -> 'b = <fun>
 
let add x y = x + y ;;
val add : int -> int -> int = <fun>

Překladač tedy odvodí typ funkcí až ve chvíli, kdy jsou tyto funkce volány (stále se však jedná o čas překladu, nikoli čas běhu aplikace).

Poznámka: povšimněte si, že se nyní rozlišují typy 'a a 'b, protože nikde není naznačeno, že by funkce first či second musela akceptovat parametry se shodnými typy.

11. n-tice

Ze složených datových typů jsou v programovacím jazyku OCaml samozřejmě podporovány n-tice. Ty mohou obsahovat prvky libovolných typů a stejně jako v jazyku F# i zde je typ n-tice jako celku odvozen od typů jednotlivých prvků.

let x = (1, 2, 3);;

Typ této n-tice se zapisuje následovně:

val x : int * int * int = (1, 2, 3)
Poznámka: povšimněte si operátoru * v zápisu typu n-tice. Tento operátor naznačuje, že se jedná o kartézský součin dvou množin (tvořených všemi prvky jednotlivých typů). Asi ještě lépe to bude patrné na tomto příkladu:
(true, true) ;;
 
- : bool * bool = (true, true)

Typ této n-tice je bool * bool, tedy kartézský součin dvou množin s prvky typu bool (true či false), takže lze snadno odvodit, kolik unikátních hodnot tento typ reprezentuje.

Můžeme se pokusit zapsat i složitější n-tici:

let x = (1, "foo", (1,2,"bar"));;

Typ této n-tice je:

val x : int * string * (int * int * string) = (1, "foo", (1, 2, "bar"))

12. Záznamy

Jedním z nejužitečnějších složených, (resp. možná přesněji řečeno strukturovaných) datových typů jsou v programovacím jazyku OCaml záznamy (records), v nichž mohou být uloženy prvky taktéž libovolného typu, ovšem na rozdíl od n-tic jsou tyto prvky pojmenovány. Zde je již nutné definovat nový datový typ s explicitním určením typů jednotlivých položek (další možnosti si popíšeme jindy). Datový typ car může být definován takto:

type car = {
  color: string;
  model: string;
  manufacturer: string;
  year: int;
}
Poznámka: oproti programovacímu jazyku F# zde můžeme vidět jeden poměrně velký rozdíl – prvky struktury začínají malými písmeny.

Vytvoření proměnné s hodnotou tohoto typu se zapisuje následujícím stylem:

let toyota :car = {color="silver"; model="Corolla"; manufacturer="Toyota"; year=1986};;

Typ této hodnoty je vypsán ve stylu, kdy se již neopisují typy prvků:

val toyota : car
Poznámka: pro novou proměnnou toyota platí všechny vlastnosti proměnných zmíněné výše, tj. neměnitelnost atd.

Přístup (pro čtení) k prvkům datové struktury je triviální, resp. přesněji řečeno se nijak zvlášť neliší od mainstreamových programovacích jazyků:

# toyota.model;;
 
- : string = "Corolla"

13. Typová inference u záznamů

I u proměnných či parametrů typu záznam se uplatňuje typová inference, což konkrétně znamená, že například v následujícím příkladu nemusíme u proměnné toyota explicitně deklarovat její typ:

type car = {
  color: string;
  model: string;
  manufacturer: string;
  year: int;
}
 
let toyota = {color="silver"; model="Corolla"; manufacturer="Toyota"; year=1986};;

Výsledkem bude tato hodnota:

val toyota : car =
  {color = "silver"; model = "Corolla"; manufacturer = "Toyota"; year = 1986}

Někdy je ovšem nutné překladači pomoci a nespoléhat se na typovou inferenci:

cyber23

type point = {
  x:int;
  y:int;
}
 
type vector = {
  x:int;
  y:int;
}
 
let p1 = {x=10; y=10;};;
let p2:point = {x=10; y=10;};;

V tomto případě překladač rozhodne, že hodnota p1 bude typu vector a nikoli point:

- : vector = {x = 10; y = 10}
Poznámka: lepší by v tomto případě bylo rozdělení do jmenných prostorů, o čemž se zmíníme příště.

14. 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:

# Příklad Popis příkladu Cesta
1 hello_world1.ml zavolání funkce print_string https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/hello_world1.ml
2 hello_world2.ml zavolání funkce printf.Printf https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/hello_world2.ml
       
3 function.ml definice funkce https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/function.ml
4 lambda.ml anonymní funkce https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/lambda.ml
       
5 function_type1.ml explicitní specifikace typu návratové hodnoty funkce https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/function_type1.ml
6 function_type2.ml explicitní specifikace typu návratové hodnoty funkce https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/function_type2.ml
       
7 call_function1.ml definice jednoduché funkce s jejím zavoláním https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/call_function1.ml
8 call_function2.ml definice jednoduché funkce s jejím zavoláním https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/call_function2.ml
9 call_function3.ml použití operátoru + pro dvojici hodnot typu float https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/call_function3.ml
10 call_function4.ml použití operátoru +. pro dvojici hodnot typu float https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/call_function4.ml
11 call_function5.ml plná deklarace funkce bez syntaktického cukru https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/call_function5.ml
12 call_function6.ml plná deklarace funkce bez syntaktického cukru https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/call_function6.ml
       
13 local_binding1.ml definice lokálních symbolů https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/local_binding1.ml
14 local_binding2.ml definice lokálních symbolů https://github.com/tisnik/ocaml-examples/tree/master/arti­cle01/local_binding2.ml
       
15 basic_binding.ml navázání hodnoty na symbol (deklarace proměnné) https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/basic_binding.ml
16 print_variable.ml tisk hodnoty proměnné https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/print_variable.ml
17 variables_and_functions.ml předání proměnné do funkce https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/variables_and_functi­ons.ml
18 redefine_symbol1.ml pokus o redefinici symbolu https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/redefine_symbol1.ml
19 redefine_symbol2.ml pokus o redefinici symbolu (složitější příklad) https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/redefine_symbol2.ml
       
20 equal_operator1.ml operátor = https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/equal_operator1.ml
21 equal_operator2.ml operátor = https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/equal_operator2.ml
       
22 immutable_variable.ml „změna“ neměnitelné proměnné https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/immutable_variable.ml
22 mutable_variable.ml změna měnitelné proměnné https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/mutable_variable.ml
23 shadow.ml shadowing symbolu https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/shadow.ml
24 incr.ml standardní funkce incr https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/incr.ml
25 ident.ml nejjednodušší polymorfická funkce https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/ident.ml
       
26 tuple1.ml datový typ n-tice (tuple) https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/tuple1.ml
27 tuple2.ml datový typ n-tice (tuple) https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/tuple2.ml
28 record1.ml datový typ záznam (record), deklarace proměnné tohoto typu https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/record1.ml
29 record2.ml datový typ záznam (record) a typová inference https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/record2.ml
       
30 unit.ml datový typ unit a rozdíl oproti funkcím bez parametrů https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/unit.ml
31 polymorphic.ml použití polymorfických funkcí https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/polymorphic.ml
32 two_same_records.ml dva datové typy záznam se shodnými prvky https://github.com/tisnik/ocaml-examples/tree/master/arti­cle02/two_same_records.ml

15. Odkazy na Internetu

  1. General-Purpose, Industrial-Strength, Expressive, and Safe
    https://ocaml.org/
  2. OCaml playground
    https://ocaml.org/play
  3. Online Ocaml Compiler IDE
    https://www.jdoodle.com/compile-ocaml-online/
  4. Get Started – OCaml
    https://www.ocaml.org/docs
  5. Get Up and Running With OCaml
    https://www.ocaml.org/docs/up-and-running
  6. Better OCaml (Online prostředí)
    https://betterocaml.ml/?ver­sion=4.14.0
  7. OCaml file extensions
    https://blog.waleedkhan.name/ocaml-file-extensions/
  8. First thoughts on Rust vs OCaml
    https://blog.darklang.com/first-thoughts-on-rust-vs-ocaml/
  9. Standard ML of New Jersey
    https://www.smlnj.org/
  10. Programming Languages: Standard ML – 1 (a navazující videa)
    https://www.youtube.com/wat­ch?v=2sqjUWGGzTo
  11. 6 Excellent Free Books to Learn Standard ML
    https://www.linuxlinks.com/excellent-free-books-learn-standard-ml/
  12. SOSML: The Online Interpreter for Standard ML
    https://sosml.org/
  13. ML (Computer program language)
    https://www.barnesandnoble­.com/b/books/other-programming-languages/ml-computer-program-language/_/N-29Z8q8Zvy7
  14. Strong Typing
    https://perl.plover.com/y­ak/typing/notes.html
  15. What to know before debating type systems
    http://blogs.perl.org/user­s/ovid/2010/08/what-to-know-before-debating-type-systems.html
  16. Types, and Why You Should Care (Youtube)
    https://www.youtube.com/wat­ch?v=0arFPIQatCU
  17. DynamicTyping (Martin Fowler)
    https://www.martinfowler.com/bli­ki/DynamicTyping.html
  18. DomainSpecificLanguage (Martin Fowler)
    https://www.martinfowler.com/bli­ki/DomainSpecificLanguage­.html
  19. Language Workbenches: The Killer-App for Domain Specific Languages?
    https://www.martinfowler.com/ar­ticles/languageWorkbench.html
  20. Effective ML (Youtube)
    https://www.youtube.com/watch?v=-J8YyfrSwTk
  21. Why OCaml (Youtube)
    https://www.youtube.com/wat­ch?v=v1CmGbOGb2I
  22. Try OCaml
    https://try.ocaml.pro/
  23. CSE 341: Functions and patterns
    https://courses.cs.washin­gton.edu/courses/cse341/04wi/lec­tures/03-ml-functions.html
  24. Comparing Objective Caml and Standard ML
    http://adam.chlipala.net/mlcomp/
  25. 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
  26. Cheat Sheets (pro OCaml)
    https://www.ocaml.org/doc­s/cheat_sheets.html
  27. Think OCaml: How to Think Like a (Functional) Programmer
    https://www.greenteapress­.com/thinkocaml/thinkocam­l.pdf
  28. The OCaml Language Cheat Sheet
    https://ocamlpro.github.io/ocaml-cheat-sheets/ocaml-lang.pdf
  29. Syllabus (FAS CS51)
    https://cs51.io/college/syllabus/
  30. Abstraction and Design In Computation
    http://book.cs51.io/
  31. Learn X in Y minutes Where X=Standard ML
    https://learnxinyminutes.com/doc­s/standard-ml/
  32. CSE307 Online – Summer 2018: Principles of Programing Languages course
    https://www3.cs.stonybrook­.edu/~pfodor/courses/summer/cse307­.html
  33. CSE307 Principles of Programming Languages course: SML part 1
    https://www.youtube.com/wat­ch?v=p1n0_PsM6hw
  34. CSE 307 – Principles of Programming Languages – SML
    https://www3.cs.stonybrook­.edu/~pfodor/courses/summer/CSE307/L01_SML­.pdf
  35. History of programming languages
    https://devskiller.com/history-of-programming-languages/
  36. History of programming languages (Wikipedia)
    https://en.wikipedia.org/wi­ki/History_of_programming_lan­guages
  37. The Evolution Of Programming Languages
    https://www.i-programmer.info/news/98-languages/8809-the-evolution-of-programming-languages.html
  38. Evoluce programovacích jazyků
    https://ccrma.stanford.edu/cou­rses/250a-fall-2005/docs/ComputerLanguagesChart.png
  39. Currying
    https://sw-samuraj.cz/2011/02/currying/
  40. Currying (Wikipedia)
    https://en.wikipedia.org/wi­ki/Currying
  41. Currying (Haskell wiki)
    https://wiki.haskell.org/Currying
  42. Haskell Curry
    https://en.wikipedia.org/wi­ki/Haskell_Curry
  43. Moses Schönfinkel
    https://en.wikipedia.org/wi­ki/Moses_Sch%C3%B6nfinkel
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. Python to OCaml: Retrospective
    http://roscidus.com/blog/blog/2014/06/0­6/python-to-ocaml-retrospective/
  51. Why does Cambridge teach OCaml as the first programming language?
    https://www.youtube.com/wat­ch?v=6APBx0WsgeQ
  52. OCaml and 7 Things You Need To Know About It In 2021 | Functional Programming | Caml
    https://www.youtube.com/wat­ch?v=s0itOsgcf9Q
  53. OCaml 2021 – 25 years of OCaml
    https://www.youtube.com/watch?v=-u_zKPXj6mw
  54. Introduction | OCaml Programming | Chapter 1 Video 1
    https://www.youtube.com/wat­ch?v=MUcka_SvhLw&list=PLre5AT9JnKShBO­PeuiD9b-I4XROIJhkIU
  55. Functional Programming – What | OCaml Programming | Chapter 1 Video 2
    https://www.youtube.com/wat­ch?v=JTEwC3HihFc&list=PLre5AT9JnKShBO­PeuiD9b-I4XROIJhkIU&index=2
  56. Functional Programming – Why Part 1 | OCaml Programming | Chapter 1 Video 3
    https://www.youtube.com/wat­ch?v=SKr3ItChPSI&list=PLre5AT9JnKShBO­PeuiD9b-I4XROIJhkIU&index=3
  57. Functional Programming – Why Part 2 | OCaml Programming | Chapter 1 Video 4
    https://www.youtube.com/wat­ch?v=eNLm5Xbgmd0&list=PLre5AT9JnKShBO­PeuiD9b-I4XROIJhkIU&index=4

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.