Lekce 2 - Větvení a cykly v CoffeeScriptu
V minulém dílu, Úvod do CoffeeScriptu, jsme si udělali úvod do tohoto jazyka a zmínili základní syntaxi.
Dnes si ukážeme větvení a cykly.
Větvení
Jak možná očekáváte, pro základní větvení použijeme tradiční
slůvka if
/else
a jak jsme si již zvykli, vynecháme
závorky:
x = 5 if x == 5 alert 'ano' else if x is 4 or x is 6 alert 'těsně vedle' else alert 'ne'
JavaScript:
var x; x = 5; if (x === 5) { alert('ano'); } else if (x === 4 || x === 6) { alert('těsně vedle'); } else { alert('ne'); }
Na kódu můžeme vypozorovat, že CoffeeScript převádí ==
na
===
. Nutí vás tedy explicitně převádět hodnoty, jestliže
např. chcete, aby se string '40' rovnal číslu 40. Také přidává aliasy
různým operátorům (or
je ||
, is
je
===
atd.), aby kód skutečně připomínal spíše jazyk nežli
soubor matematických zápisů. Můžete však používat operátory jak je
znáte z JS. Tabulku s různými operátory najdete na konci článku.
Z Ruby si CoffeeScript vypůjčil klíčové slovo unless
,
které je vlastně jen if not
a můžeme použít i slovo
then
, aby se to hezky vešlo na jediný řádek:
unless false then console.log 2 # Vždy vypíše do konzole číslo 2.
Někdy můžete chtít vložit do proměnné hodnotu jen tehdy, když je splněna podmínka. K tomu můžete použít postfixový tvar:
kafe = 'Instant' if maloCasu
JavaScript:
var kafe; if (maloCasu) { kafe = 'Instant'; }
Když přiřadíme větvení k proměnné, CoffeeScript jej převede na ternární operátor:
nalada = if den is 'vsedni' and not prazdniny then 'spatna' else 'dobra'
JavaScript:
var nalada; nalada = den === 'vsedni' && !prazdniny ? 'spatna' : 'dobra';
Znalci Pythonu poznají zřetězené porovnávání proměnných, které CoffeeScript také podporuje:
if x > y < z >= a <= b is c isnt d console.log 'eh...ok...'
JavaScript:
if ((((((x > y && y < z) && z >= a) && a <= b) && b === c) && c !== d)) { console.log('eh...ok...'); }
Existenční operátor
Chceme-li zjistit, zda je proměnná/objekt definován(a) a není null,
můžeme použít tzv. existenční operátor - ?
(neplést s
ternárním operátorem z jiných jazyků), který vrací true
v
případě, že proměnná není null
nebo
undefined
.
alert 'To je katastrofa!' unless kavovar?
JavaScript:
if (typeof kavovar === "undefined" || kavovar === null) { alert('To je katastrofa!'); }
Lze použít i přiřazení hodnoty do proměnné v případě, že
proměnná není null
(musí být však deklarována):
x = undefined
x ?= 5
JavaScript:
var x; x = void 0; if (x == null) { x = 5; }
Pozor! Na rozdíl od JS je v CoffeeScript slovo undefined
klíčové, nemůžete mít tedy proměnnou s tímto jménem.
Existenční operátor jde použít samozřejmě i na objekty a funkce, takže lze tvořit klenoty jako:
objekt?.funkce? parametr if parametr?
JavaScript:
if (typeof parametr !== "undefined" && parametr !== null) { if (typeof objekt !== "undefined" && objekt !== null) { if (typeof objekt.funkce === "function") { objekt.funkce(parametr); } } }
Zde už to začíná být opravdu nechutné a to jsme ani nenakousli OOP.
Switch
Dostali jsme se k poslední důležité části větvení a tou je samozřejmě switch. Jeho syntaxe v CoffeeScriptu je následující:
switch spanek when 'spatny' then mnozstviKofeinu = 'hodne' when 'prumerny' then mnozstviKofeinu = 'malo' when 'dobry' then do nepijKafe else alert '???'
JavaScript:
var mnozstviKofeinu; switch (spanek) { case 'spatny': mnozstviKofeinu = 'hodne'; break; case 'prumerny': mnozstviKofeinu = 'malo'; break; case 'dobry': nepijKafe(); break; default: alert('asi nespíš a jsi robot'); }
Pomocí switche lze také přiřazovat hodnoty místo několika
if
/else
:
bodu = 83 znamka = switch when bodu < 60 then 5 when bodu < 70 then 4 when bodu < 80 then 3 when bodu < 90 then 2 else 1 # znamka === 2
JavaScript:
var bodu; bodu = 83; znamka = (function() { switch (false) { case !(bodu < 60): return 5; case !(bodu < 70): return 4; case !(bodu < 80): return 3; case !(bodu < 90): return 2; default: return 1; } })();
Cykly
While
Základní while
cyklus:
while podminka alert 'Cykluju...' # 'bezna' forma alert 'Cykluju...' while podminka # postfix forma
Oba kódy se zkompilují do:
while (podminka) { alert('Cykluju...'); }
Podobně jako unless
je if not
, until
je while not
:
alert 'Cykluju a podminka neni pravdiva...' until podminka
JavaScript:
while (!podminka) { alert('Cykluju a podminka neni pravdiva...'); }
Buďte s until
i unless
opatrní a nepřidávejte
do podmínek negace, kód se bude špatně číst. Také by se s těmito slovy
nemělo používat else
.
Pomocí loop
vytvoříme nekonečný cyklus:
loop
alert 'Nekončíííím...'
JavaScript:
while (true) { alert('Nekončíííím...'); }
Když jsem v minulém díle psal, že „Co jde v JS, jde i v
CoffeeScriptu“, nebyla to tak docela pravda, jak (nejen) nyní uvidíte.
CoffeeScript nemá do-while
cyklus, jelikož slovo do
v CoffeeScriptu znamená 'volej funkci', jde jej však lehce nahradit
následujícím zápisem:
loop ### tělo cyklu ### break unless podminka
JavaScript:
while (true) { /* tělo cyklu */ if (!podminka) { break; } }
Pomocí cyklu lze vytvářet pole:
cislo = 10 pole = while cislo-- cislo # pole = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
JavaScript:
var cislo, pole; cislo = 10; pole = (function() { var _results; _results = []; while (cislo--) { _results.push(cislo); } return _results; })();
A když chceme, aby cyklus (ne)projížděl určitými hodnotami, použijeme
slovo when
. Toto se nám bude obzvlášť hodit později při
for-in
a for-of
cyklech. Tento kód vám podobně jako
v minulém příkladu vytvoří pole, ale bez sudých čísel:
cislo = 10 pole = while cislo-- when cislo % 2 isnt 0 cislo # pole = [9, 7, 5, 3, 1]
Část JS kódu po úpravě:
//... while (cislo--) { if (cislo % 2 !== 0) { _results.push(cislo); } } //...
For
Pro základní for
cyklus použijeme nám již známé
n-tice:
for [1..10] # dvě tečky <= console.log 'a' for [1...10] # tři tečky < console.log 'a'
JavaScript:
var _i, _j; for (_i = 1; _i <= 10; _i++) { console.log('a'); } for (_j = 1; _j < 10; _j++) { console.log(_j); }
Kdybychom chtěli vypsat číslo, které je zrovna projížděno cyklem:
for i in [1..10] console.log i
V JS for cyklu bude následující:
for (i = _i = 1; _i <= 10; i = ++_i)
Není to zrovna nejelegantnější řešení, ale ta proměnná navíc snad nikoho nezabije. Mohli by jste samozřejmě proměnnou i nahradit _i, avšak pro každý další cyklus se tvoří nová proměnná (_j, _k atd...), a v .coffee souboru ji nevidíte, mohli byste s tímto způsobem narazit.
Nechceme vždy řídící proměnnou cyklu zvyšovat o 1, máme naštěstí k
dispozici slovo by
:
for i in [50..0] by -5
JavaScript:
for (i = _i = 50; _i >= 0; i = _i += -5)
Cyklus for-in
v CoffeeScriptu používáme také na pole
(Pozor! toto je velký rozdíl oproti JavaScriptu, kde je tento
cyklus používán na objekty). Ukážeme si příklad na známém poli s
kávami a nebudeme chtít rozpustnou:
kavy = ['Alžírská', 'Espresso', 'Cappuccino', 'Latte', 'Rozpustná', 'Vídeňská'] console.log kava for kava in kavy when kava isnt 'Rozpustná'
JavaScript:
var kava, kavy, _i, _len; kavy = ['Alžírská', 'Espresso', 'Cappuccino', 'Latte', 'Rozpustná', 'Vídeňská']; for (_i = 0, _len = kavy.length; _i < _len; _i++) { kava = kavy[_i]; if (kava !== 'Rozpustná') { console.log(kava); } }
Od ES6 existuje cyklus for-of
pro pole, CoffeeScript však volí
toto řešení kvůli kompatibilitě. Co je tedy ekvivalentem
for-in
v CoffeeScriptu? Ironicky je to for-of
. Pro
příklad si vypůjčíme kavárnu z prvního dílu:
kavarna = jmeno: "Kofeinová pumpa" rokZalozeni: 2001 freeWifi: yes napojovyListek: kavy: [ "Cappuccino" "Moccaccino" "Espresso" ] nealko: [ "Sprite" "Pomerančový džus" "Voda z Marsu" ] for nazev, hodnota of kavarna console.log "#{nazev} => #{hodnota}" # jmeno => Kofeinová pumpa # rokZalozeni => 2001 # freeWifi => true # napojovyListek => [object Object]
Samotný cyklus v JS:
for (nazev in kavarna) { hodnota = kavarna[nazev]; console.log("" + nazev + ": " + hodnota); }
Co kdybychom chtěli vypsat prvních pět vlastností v objektu? Ani to není problém:
console.log (nazev for nazev of document)[0...5] # vytvoří pole a vypíše: ["vlinkColor", "linkColor", "alinkColor", "fgColor", "bgColor"]
Nedávejte mezeru mezi pravou kulatou a levou hranatou závorku, program by
pak dělal něco úplně jiného. Hlavně si zapamatuje - v JavaScriptu
používáme of
na pole, in
na objekty, v
CoffeeScriptu je to naopak.
Uf, tak jsme se dostali ke konci. Na závěr zde máte tabulku s operátory, jak jsem slíbil:
is, == | === |
isnt, != | !== |
not | ! |
and | && |
or | || |
in | není překládán (of) |
of | in |
a // b | Math.floor(a / b) |
a %% b | (a % b +b ) % b) |
Příště, v lekci Funkce a výjimky v CoffeeScript, se podíváme na hlavní pilíř JavaScriptu - funkce.