Definice proměnných a funkcí
V prvním díle našeho seriálu jsme vygenerovali kostru jednoduché aplikace v Reasonu a nainstalovali plugin pro Reason do Visual Studia Code. Dnes začneme v Reasonu programovat. Otevřeme soubor src/page.re
. Kromě zvýrazňování syntaxe nám Visual Studio Code ukazuje i typy některých proměnných.
Typy se zobrazují nad řádkem, kde je proměnná deklarována. Například proměnná handleClick
má typ ('a, 'b) => unit
(přesný význam tohoto typu vysvětlíme později).
Zadefinujme novou proměnnou crowns
. Jak to provést? Pod řádek s definicí proměnné component
(řádek začínající let component
) vložme následující:
let crowns = 200;
Právě jsme zadefinovali naši první proměnnou! Její název je crowns
, její typ je int
a její hodnota je 200
. Na rozdíl od mnoha populárních jazyků nejde v Reasonu do proměnné přiřadit jiná hodnota.
Zkusme zadefinovat druhou proměnnou. Pod řádek crowns
přidejme
let crownsForOneDollar = 25.4;
Proměnná crownsForOneDollar
má typ float
. Nyní můžeme spočítat:
let dollars = float_of_int(crowns) /. crownsForOneDollar;
Všimněme si dvou věcí:
- Za lomítkem je tečka. Operátor
/.
přijímá dvafloat
y a vracífloat
. Zatímco/
(bez tečky) přijímá dvaint
y a vracíint
. - Reason neprovádí žádné implicitní konverze. Je tedy třeba ručně převést
int
nafloat
.
Oboje pomáhá typové inferenci. Navíc absence implicitních konverzí dělá kód jednodušším na pochopení.
float_of_int
je funkce ze standardní knihovny stejně jako /.
. Vlastní funkci vytvoříme pomocí let
:
let crownsToForeignCurrency = (crownsPerUnit, crowns) => float_of_int(crowns) /. crownsPerUnit;
Funkce se jmenuje crownsToForeignCurrency
. Nalevo od =>
v našem kódu je seznam parametrů funkce. Napravo od =>
je tělo funkce. Typ funkce je (float, int) => float
. Nalevo od =>
jsou typy parametrů, napravo od =>
je typ návratové hodnoty.
Příklad použití:
let dollars2 = crownsToForeignCurrency(crownsForOneDollar, crowns);
Jiný příklad použití:
let crownsToDollars = crownsToForeignCurrency(crownsForOneDollar);
Výsledkem tohoto volání je funkce typu (int) => float
, jenž převádí koruny na dolary. Co se stalo? Funkce crownsToForeignCurrency
potřebuje dva argumenty, když predáme pouze jeden, není to chyba, vznikne funkce, která bude čekat na ten druhý.
Obecně, když máme funkci s n parametry a předáme jí jeden argument, dostaneme funkci, která čeká na zbývajících n – 1 argumentů. Můžeme tedy psát
let dollars3 = crownsToDollars(crowns);
Každá funkce v Reasonu má právě jeden parametr
Ve skutečnosti v Reasonu mají všechny funkce právě jeden parametr. Funkce se třemi parametry a
, b
, c
je ve skutečnosti funkce s jedním parametrem a
, která vrací funkci s jedním parametrem b
, která vrací funkci s jedním parametrem c
a tato poslední funkce počítá návratovou hodnotu poté, co dostane argument pro svůj jediný parametr c
.
Tudíž zápis
let f = (a, b, c) => Js.log(a ++ b ++ c);
je pouze zkratkou za
let f = (a) => (b) => (c) => Js.log(a ++ b ++ c);
Funkce g
, g2
a g3
dělají totéž:
let g = f("Acko"); let g2 = (b) => (c) => Js.log("Acko" ++ b ++ c); let g3 = (b, c) => Js.log("Acko" ++ b ++ c);
Typy se chovají podobně. Existuje řada možností, jak zapsat typ funkce f
:
(string, string, string) => unit (string) => (string) => (string) => unit (string) => (string, string) => unit (string, string) => (string) => unit (string) => ((string) => (string) => unit)
Typ unit
značí, že návratová hodnota funkce není zajímavá (funkci f
voláme kvůli výpisu do konzole prohlížeče, nikoliv proto, že chceme spočítat návratovou hodnotu).
Rovněž volání funkce lze provést několika způsoby:
f("a", "b", "c"); f("a")("b", "c"); f("a", "b")("c"); f("a")("b")("c");
Pojmenované argumenty
Nepříjemné je, že z volání funkce crownsToForeignCurrency
nejde na první pohled poznat, co je kurz a co počet korun:
let dollars4 = crownsToForeignCurrency(25.4, 200);
Tuto vadu odstraníme tak, že definicí funkce vynutíme pojmenování jednoho z argumentů pomocí vlnky:
let crownsToForeignCurrency2 = (~crownsPerUnit, crowns) => float_of_int(crowns) /. crownsPerUnit;
Změna se projeví i v typu funkce. Díky pojmenovanému argumentu je volání funkce srozumitelnější:
let dollars5 = crownsToForeignCurrency2(~crownsPerUnit=25.4, 200);
Zobrazení výsledku ve stránce
Nyní je na čase prezentovat výsledek našeho výpočtu ve webové stránce. Využijeme k tomu Reactí komponentu Page
, kterou vytváří funkce make
. make
vrací popis komponenty. Funguje tak, že vezme existující popis komponenty, jenž je uložen v proměnné component
, udělá jeho kopii a v této kopii změní pole render
. V poli render
je funkce, která určuje, jak se komponenta vykreslí.
Abychom prezentovali výsledky našeho převodu korun na dolary, upravíme právě funkci v render
:
let make = (~message, _children) => { ...component, render: (self) => <div onClick=(self.handle(handleClick))> (ReasonReact.stringToElement(message)) (ReasonReact.stringToElement({j|BTW $crowns CZK is equal to $dollars5 USD!|j})) </div> };
Syntax {j|řetězec|j}
vytváří řetězec. Na rozdíl od řetězců uzavřených mezi dvojité uvozovky můžeme do těchto řetězců substituovat obsah proměnných a používat Unicode.
Závěr
V příštím díle dokončíme aplikaci převodník měn. Při tom se naučíme o záznamech v Reasonu, podíváme se na stavové komponenty v Reactu a také na to, jak v Reactu zpracovávat události z komponent.