Coconut: zápis některých operátorů s využitím Unicode

6. 6. 2024
Doba čtení: 34 minut

Sdílet

 Autor: Depositphotos
Coconut nabízí programátorům mnoho konceptů i technik. Dnes se seznámíme s alternativním způsobem zápisu některých operátorů s využitím Unicode znaků a definicí nových unárních i binárních operátorů.

Obsah

1. Částečně vyhodnocená funkce fmap

2. Funkce vyššího řádu fmap určená pro zpracování sekvencí

3. Kombinace funkce map/fmap a operátoru |>

4. Klasika ze světa funkcionálního programování – funkce vyššího řádu reduce

5. Funkce vyššího řádu takewhile a dropwhile

6. Zkrácený způsob zápisu volání funkcí reduce, takewhile a dropwhile

7. Alternativní zápis operátorů jazyka Coconut s využitím Unicode znaků

8. Definice nových binárních operátorů

9. Definice nových unárních operátorů

10. Infixový zápis při volání funkcí

11. Infixový zápis při definici nových funkcí

12. Priorita volání funkcí zapsaných infixovým způsobem

13. Kompatibilita s Pythonem 2 a Pythonem 3

14. Kontrola verze Pythonu v runtime

15. Klíčová slova async a await

16. Nelokální proměnné

17. Mroží operátor

18. Obsah navazujícího článku

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

20. Odkazy na Internetu

1. Částečně vyhodnocená funkce fmap

V předchozím článku o programovacím jazyku Coconut jsme se kromě dalších věcí zmínili i o konstrukci částečně vyhodnocených funkcí (partial functions). Použití tohoto konceptu jsme si ukázali na několika funkcích, které násobily svoje parametry (dva, tři či čtyři), takže jejich částečné vyhodnocení spočívalo v dosazení celočíselné hodnoty do jednoho nebo do více parametrů; výsledkem byla nová funkce. Ovšem částečně lze vyhodnotit například i funkci vyššího řádu map, resp. v programovacím jazyce Coconut spíše funkci fmap tak, že do ní dosadíme lambda výraz (či plnohodnotnou anonymní funkci) a necháme si tak vygenerovat nějakou jinou funkci, která tento lambda výraz bude postupně aplikovat na své parametry.

Ukažme si popsaný postup na příkladu konstrukce nové funkce nazvané double, která dokáže získat sekvenci a vynásobit všechny prvky této sekvence dvěma:

double = fmap$(x => x*2)
 
print(double([1, 2, 3, 4]))
print(double((1, 2, 3, 4)))
print(double(range(10)))

Překlad, resp. přesněji řečeno transpřeklad předchozího skriptu z Coconutu do Pythonu dopadne následovně:

# Compiled Coconut: -----------------------------------------------------------
 
double = _coconut_partial(fmap, lambda x: x * 2)  #1 (line in Coconut source)
 
print(double([1, 2, 3, 4]))  #3 (line in Coconut source)
print(double((1, 2, 3, 4)))  #4 (line in Coconut source)
print(double(range(10)))  #5 (line in Coconut source)

2. Funkce vyššího řádu fmap určená pro zpracování sekvencí

V programovacím jazyce Coconut došlo k rozšíření některých funkcí (konkrétně vestavěných funkcí, které není zapotřebí importovat), jejichž základní podobu již známe přímo z jazyka Python. Tyto funkce je možné využít zejména při zpracování různých sekvencí, tj. n-tic, seznamů, iterátorů, vlastně i řetězců apod. První užitečnou funkcí (konkrétně funkcí vyššího řádu – protože jako svůj první parametr akceptuje jinou funkci) je funkce nazvaná fmap, která pracuje do značné míry stejně jako standardní Pythonovská funkce map (aplikace jiné zvolené funkce na sekvenci), ovšem výsledek je stejného typu, jako vstupní sekvence.

Podívejme se nyní na to, jakým způsobem lze tuto funkci aplikovat na seznamy, n-tice a taktéž na objekt typu range. Pro porovnání navíc voláme i původní Pythonovskou funkci map nad stejnými vstupními daty:

print(map(x => x*2, [1, 2, 3, 4]))
print(list(map(x => x*2, [1, 2, 3, 4])))
print(fmap(x => x*2, [1, 2, 3, 4]))
 
print()
 
print(map(x => x*2, (1, 2, 3, 4)))
print(list(map(x => x*2, (1, 2, 3, 4))))
print(fmap(x => x*2, (1, 2, 3, 4)))
 
print()
 
print(map(x => x*2, range(10)))
print(list(map(x => x*2, range(10))))
print(fmap(x => x*2, range(10)))

Výsledky ukazují, jak se liší typ výsledných hodnot produkovaných funkcemi map a fmap. Povšimněte si, že funkce fmap vždy vrátí sekvenci stejného typu, jaký má její vstupní parametr (což je samozřejmě taktéž sekvence):

map(<function <lambda> at 0x7f8bf9365080>, [1, 2, 3, 4])
[2, 4, 6, 8]
[2, 4, 6, 8]
 
map(<function <lambda> at 0x7f8bf9365080>, (1, 2, 3, 4))
[2, 4, 6, 8]
(2, 4, 6, 8)
 
map(<function <lambda> at 0x7f8bf9365080>, range(0, 10))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
map(<function <lambda> at 0x7f8bf9365080>, range(0, 10))

Pro zajímavost se ještě podívejme na výsledek transpřekladu do Pythonu, i když zde nic zajímavého v tomto případě nenalezneme, protože se pouze volá funkce fmap definovaná výše (tuto definici jsme z výpisu vynechali):

# Compiled Coconut: -----------------------------------------------------------
 
print(map(lambda x: x * 2, [1, 2, 3, 4]))  #1 (line in Coconut source)
print(list(map(lambda x: x * 2, [1, 2, 3, 4])))  #2 (line in Coconut source)
print(fmap(lambda x: x * 2, [1, 2, 3, 4]))  #3 (line in Coconut source)
 
print()  #5 (line in Coconut source)
 
print(map(lambda x: x * 2, (1, 2, 3, 4)))  #7 (line in Coconut source)
print(list(map(lambda x: x * 2, (1, 2, 3, 4))))  #8 (line in Coconut source)
print(fmap(lambda x: x * 2, (1, 2, 3, 4)))  #9 (line in Coconut source)
 
print()  #11 (line in Coconut source)
 
print(map(lambda x: x * 2, range(10)))  #13 (line in Coconut source)
print(list(map(lambda x: x * 2, range(10))))  #14 (line in Coconut source)
print(fmap(lambda x: x * 2, range(10)))  #15 (line in Coconut source)

3. Kombinace funkce map/fmap a operátoru |>

Výše uvedený demonstrační příklad by se ovšem dal v případě potřeby zapsat i odlišným způsobem, například s využitím operátoru |>, který zajistí zřetězení funkcí tak, že výsledek (či výsledky) jedné funkce jsou předány na vstup další funkce. Výsledný zdrojový kód se tak do určité míry podobá kódu, který bychom napsali v jazyce OCaml nebo F#. Navíc ještě namísto Pythonovského způsobu zápisu lambda výrazů použijeme zkrácený zápis založený na operátoru =>, přičemž výsledek bude vypadat takto:

map(x => x*2, [1, 2, 3, 4]) |> print
map(x => x*2, [1, 2, 3, 4]) |> list |> print
fmap(x => x*2, [1, 2, 3, 4]) |> print
 
print()
 
map(x => x*2, (1, 2, 3, 4)) |> print
map(x => x*2, (1, 2, 3, 4)) |> list |> print
fmap(x => x*2, (1, 2, 3, 4)) |> print
 
print()
 
map(x => x*2, range(10)) |> print
map(x => x*2, range(10)) |> list |> print
fmap(x => x*2, range(10)) |> print

A takto (prakticky stejně, jako v příkladu originálním) dopadne transpřeklad z Coconutu do Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(map(lambda x: x * 2, [1, 2, 3, 4]))  #1 (line in Coconut source)
(print)((list)(map(lambda x: x * 2, [1, 2, 3, 4])))  #2 (line in Coconut source)
(print)(fmap(lambda x: x * 2, [1, 2, 3, 4]))  #3 (line in Coconut source)
 
print()  #5 (line in Coconut source)
 
(print)(map(lambda x: x * 2, (1, 2, 3, 4)))  #7 (line in Coconut source)
(print)((list)(map(lambda x: x * 2, (1, 2, 3, 4))))  #8 (line in Coconut source)
(print)(fmap(lambda x: x * 2, (1, 2, 3, 4)))  #9 (line in Coconut source)
 
print()  #11 (line in Coconut source)
 
(print)(map(lambda x: x * 2, range(10)))  #13 (line in Coconut source)
(print)((list)(map(lambda x: x * 2, range(10))))  #14 (line in Coconut source)
(print)(fmap(lambda x: x * 2, range(10)))  #15 (line in Coconut source)

Ve skutečnosti lze ovšem celý zápis ještě více zkrátit, a to konkrétně tak, že použijeme lambda výrazy bez uvedení jména (jmen) parametrů, což je téma, kterému jsme se věnovali již v předchozím článku. V tomto případě, jak již víme, se použije jediný parametr, který je v těle lambda výrazu zapsán formou podtržítka:

map(=> _*2, [1, 2, 3, 4]) |> print
map(=> _*2, [1, 2, 3, 4]) |> list |> print
fmap(=> _*2, [1, 2, 3, 4]) |> print
 
print()
 
map(=> _*2, (1, 2, 3, 4)) |> print
map(=> _*2, (1, 2, 3, 4)) |> list |> print
fmap(=> _*2, (1, 2, 3, 4)) |> print
 
print()
 
map(=> _*2, range(10)) |> print
map(=> _*2, range(10)) |> list |> print
fmap(=> _*2, range(10)) |> print

Transpřeklad z Coconutu do Pythonu bude nepatrně odlišný, protože se bude nastavovat výchozí hodnota implicitního parametru:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(map(lambda _=None: _ * 2, [1, 2, 3, 4]))  #1 (line in Coconut source)
(print)((list)(map(lambda _=None: _ * 2, [1, 2, 3, 4])))  #2 (line in Coconut source)
(print)(fmap(lambda _=None: _ * 2, [1, 2, 3, 4]))  #3 (line in Coconut source)
 
print()  #5 (line in Coconut source)
 
(print)(map(lambda _=None: _ * 2, (1, 2, 3, 4)))  #7 (line in Coconut source)
(print)((list)(map(lambda _=None: _ * 2, (1, 2, 3, 4))))  #8 (line in Coconut source)
(print)(fmap(lambda _=None: _ * 2, (1, 2, 3, 4)))  #9 (line in Coconut source)
 
print()  #11 (line in Coconut source)
 
(print)(map(lambda _=None: _ * 2, range(10)))  #13 (line in Coconut source)
(print)((list)(map(lambda _=None: _ * 2, range(10))))  #14 (line in Coconut source)
(print)(fmap(lambda _=None: _ * 2, range(10)))  #15 (line in Coconut source)

4. Klasika ze světa funkcionálního programování – funkce vyššího řádu reduce

Další užitečnou standardní funkcí vyššího řádu, která se používá poměrně často, je funkce reduce, při jejímž použití dochází k postupné redukci prvků uložených v sekvenci, a to (postupnou) aplikací zvolené uživatelské funkce na jednotlivé prvky a po krocích počítaný mezivýsledek, jenž se většinou nazývá akumulátor. Příklad výpočtu faktoriálu deseti jsme si již uvedli v předchozím článku:

print(reduce(lambda acc, x: acc * x, range(1, 10)))
 
362880

Lambda výraz můžeme pochopitelně zapsat i zkráceně:

print(reduce((x, acc) => acc * x, range(1, 10)))
Poznámka: ve skutečnosti nám v této oblasti Coconut pomáhá jen tím, že funkci reduce není zapotřebí explicitně importovat tak, jako je tomu v Pythonu (viz též The fate of reduce() in Python 3000).

5. Funkce vyššího řádu takewhile a dropwhile

Ze sekvencí (a to i ze sekvencí nekonečných) je možné získat začátek či naopak zbytek sekvence s využitím funkcí nazvaných takewhile a dropwhile. Těmto funkcím je zapotřebí v prvním parametru předat takzvaný predikát určující, zda prvek splňuje nějakou podmínku. V případě prvního parametru předávaného do takewhile a dropwhile se jedná o běžnou funkci, popř. o funkci anonymní, která by měla akceptovat jeden parametr (hodnotu prvku ze sekvence) a vracet by měla pravdivostní hodnotu True či False, popř. None atd., který má v kontextu pravdivostních hodnot stejný význam jako False.

Návratovou hodnotou další užitečné funkce takewhile je sekvence získaná ze vstupní sekvence, ovšem vráceno je pouze prvních n prvků, pro něž predikát (typicky anonymní funkce, ale není to podmínkou) vrací hodnotu True. Nejedná se však o klasický filtr, protože ihned ve chvíli, kdy predikát poprvé vrátí hodnotu False, je sekvence ukončena. Naopak funkce dropwhile zahodí ty prvky na začátku, pro které je podmínka splněna a poté vrátí zbytek sekvence. Povšimněte si použití count, což je v jazyce Coconut generátor nekonečné sekvence celočíselných hodnot:

print(list(takewhile(x => x < 10, range(100))))
 
print(list(dropwhile(x => x < 10, range(100))))
 
print(list(takewhile(x => x < 10, (count()))))
 
print(list(takewhile(x => x < 10, (count(0)))))
 
print(list(takewhile(x => x < 10, (count(0,2)))))

Výsledky vypsané tímto skriptem by měly vypadat takto:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8]

A pro úplnost si ukažme i výsledek transpřekladu do Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
print(reduce(lambda x, acc: acc * x, range(1, 10)))  #1 (line in Coconut source)
 
print(list(takewhile(lambda x: x < 10, range(100))))  #3 (line in Coconut source)
 
print(list(dropwhile(lambda x: x < 10, range(100))))  #5 (line in Coconut source)
 
print(list(takewhile(lambda x: x < 10, (count()))))  #7 (line in Coconut source)
 
print(list(takewhile(lambda x: x < 10, (count(0)))))  #9 (line in Coconut source)
 
print(list(takewhile(lambda x: x < 10, (count(0, 2)))))  #11 (line in Coconut source)

6. Zkrácený způsob zápisu volání funkcí reduce, takewhile a dropwhile

Skript z předchozí kapitoly se opět můžeme pokusit přepsat do kratší podoby založené na použití operátoru |> určeného pro zřetězení volání funkcí a taktéž operátoru =>, jenž je určený pro zkrácený zápis lambda výrazu. Příklad by tedy mohl vypadat takto:

reduce((x, acc) => acc * x, range(1, 10)) |> print
 
takewhile(x => x < 10, range(100)) |> list |> print
 
dropwhile(x => x < 10, range(100)) |> list |> print
 
takewhile(x => x < 10, (count())) |> list |> print
 
takewhile(x => x < 10, (count(0))) |> list |> print
 
takewhile(x => x < 10, (count(0,2))) |> list |> print

Transpřeklad do Pythonu se vlastně nebude příliš lišit od původního příkladu/skriptu:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(reduce(lambda x, acc: acc * x, range(1, 10)))  #1 (line in Coconut source)
 
(print)((list)(takewhile(lambda x: x < 10, range(100))))  #3 (line in Coconut source)
 
(print)((list)(dropwhile(lambda x: x < 10, range(100))))  #5 (line in Coconut source)
 
(print)((list)(takewhile(lambda x: x < 10, (count()))))  #7 (line in Coconut source)
 
(print)((list)(takewhile(lambda x: x < 10, (count(0)))))  #9 (line in Coconut source)
 
(print)((list)(takewhile(lambda x: x < 10, (count(0, 2)))))  #11 (line in Coconut source)

Ještě kratší způsob zápisu, který využívá faktu, že predikáty předávané do funkcí vyššího řádu takewhile a dropwhile mívají jediný parametr, který je tak možné použít implicitně, bez nutnosti jeho pojmenování:

reduce((x, acc) => acc *  x, range(1, 10)) |> print
 
takewhile( => _<10, range(100)) |> list |> print
 
dropwhile( => _<10, range(100)) |> list |> print
 
takewhile( => _<10, (count())) |> list |> print
 
takewhile( => _<10, (count(0))) |> list |> print
 
takewhile( => _<10, (count(0,2))) |> list |> print

Překlad do Pythonu ukazuje, že se opět pro jistotu nastavuje hodnota implicitního parametru na None, čehož ovšem nevyužijeme:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(reduce(lambda x, acc: acc * x, range(1, 10)))  #1 (line in Coconut source)
 
(print)((list)(takewhile(lambda _=None: _ < 10, range(100))))  #3 (line in Coconut source)
 
(print)((list)(dropwhile(lambda _=None: _ < 10, range(100))))  #5 (line in Coconut source)
 
(print)((list)(takewhile(lambda _=None: _ < 10, (count()))))  #7 (line in Coconut source)
 
(print)((list)(takewhile(lambda _=None: _ < 10, (count(0)))))  #9 (line in Coconut source)
 
(print)((list)(takewhile(lambda _=None: _ < 10, (count(0, 2)))))  #11 (line in Coconut source)

7. Alternativní zápis operátorů jazyka Coconut s využitím Unicode znaků

Programovací jazyk Coconut se sice nesnaží ve všech ohledech napodobit můj oblíbený jazyk APL [1] [2], ovšem umožňuje (jako i některé další jazyky ze třetího tisíciletí :-) alternativní zápis některých operandů s využitím Unicode znaků. Ostatně podívejte se na následující tabulku s Unicode znaky a jejich transformací na operátory jazyka Coconut:

Znak (znaky) Unicode Původní operátor
\u21d2 „=>“
\u2192 „-<“
× \xd7 „*“
\u2191 „**“
÷ \xf7 „/“
÷/ \xf7/ „//“
\u207b „-“
\u2260 nebo ¬= \xac= „!=“
\u2264 nebo ⊆ \u2286 „<=“
\u2265 nebo ⊇ \u2287 „>=“
\u228a „<“
\u228b „>“
\u2229 „&“
\u222a „|“
« \xab „<<“
» \xbb „>>“
\u2026 „…“
λ \u03bb „lambda“
\u21a6 „|>“
\u21a4 „<|“
*↦ *\u21a6 „|*>“
↤* \u21a4* „<*|“
**↦ **\u21a6 „|**>“
↤** \u21a4** „<**|“
?↦ ?\u21a6 „|?>“
↤? ?\u21a4 „<?|“
?*↦ ?*\u21a6 „|?*>“
↤*? \u21a4*? „<*?|“
?**↦ ?**\u21a6 „|?**>“
↤**? \u21a4**? „<**?|“
\u2218 „..“
∘> \u2218> „..>“
<∘ <\u2218 „<..“
∘*> \u2218*> „..*>“
<*∘ <*\u2218 „<*..“
∘**> \u2218**> „..**>“
<**∘ <**\u2218 „<**..“
∘?> \u2218?> „..?>“
<?∘ <?\u2218 „<?..“
∘?*> \u2218?*> „..?*>“
<*?∘ <*?\u2218 „<*?..“
∘?**> \u2218?**> „..?**>“
<**?∘ <**?\u2218 „<**?..“
\u23e8 „e“ (v zápisu numerických hodnot)

8. Definice nových binárních operátorů

V jazyce Coconut je možné si dodefinovat vlastní binární operátory, tj. operátory s levým a pravým operandem. Takové operátory mají pevně stanovenou asociativitu (ale i prioritu) a musí se jednat o nějaký znak z Unicode. Podívejme se na příklad definice nového operátoru reprezentovaného znakem ⊕, který při svém zavolání ve výrazu vrátí výsledek operace modulo. Povšimněte si, že nový operátor je nejdříve nutné registrovat klíčovým slovem operator a teprve poté ho je možné definovat:

operator ⊕
 
def x ⊕  y: return x % y
 
for i in range(1, 10):
    print(10 ⊕  i)

Takový operátor bude přeložen i volán jako funkce:

# Compiled Coconut: -----------------------------------------------------------
 
 
def _coconut_op_U2295(x, y):  #3 (line in Coconut source)
    return x % y  #3 (line in Coconut source)
 
 
for i in range(1, 10):  #5 (line in Coconut source)
    print((_coconut_op_U2295)(10, i))  #6 (line in Coconut source)

Příklad definice dalšího binárního operátoru, jehož operandy mají odlišný význam a bude u něj hrát roli asociativita a (ne)komutativita:

operator ←
 
def x ←  y: return x << y
 
for i in range(0, 10):
    print(1 ←  i)

A opět si ukažme výsledek transpřekladu:

# Compiled Coconut: -----------------------------------------------------------
 
 
def _coconut_op_U2190(x, y):  #3 (line in Coconut source)
    return x << y  #3 (line in Coconut source)
 
 
for i in range(0, 10):  #5 (line in Coconut source)
    print((_coconut_op_U2190)(1, i))  #6 (line in Coconut source)

9. Definice nových unárních operátorů

Podobným způsobem jako operátory binární je ovšem možné v jazyce Coconut definovat či dodefinovat si i operátory unární. Příklad bude v tomto případě jednoduchý – dodefinujeme si totiž operátor pro výpočet druhé odmocniny reprezentovaný svým symbolem známým z matematiky:

import math
 
operator √
 
def √x: return math.sqrt(x)
 
for i in range(0, 10):
    print(√i)

Výsledkem transpřekladu je opět běžná funkce:

# Compiled Coconut: -----------------------------------------------------------
 
import math  #1 (line in Coconut source)
 
 
@_coconut_tco  #5 (line in Coconut source)
def _coconut_op_U221a(x):  #5 (line in Coconut source)
    return _coconut_tail_call(math.sqrt, x)  #5 (line in Coconut source)
 
 
for i in range(0, 10):  #7 (line in Coconut source)
    print((_coconut_op_U221a)(i))  #8 (line in Coconut source)

10. Infixový zápis při volání funkcí

Při volání funkcí akceptujících dva parametry (ovšem ani více, ani méně) lze v jazyce Coconut použít infixový zápis, v němž je první operand zapsán před jméno funkce, samotné jméno funkce je umístěno ve zpětných apostrofech (to je v tomto případě striktně vyžadováno) a po něm je zapsán druhý operand. Tento zápis není výhodný vždy, ovšem v některých případech je čitelnější a logičtější. Příkladem může být test na typ hodnoty v rámci hierarchie tříd:

print("hello" `isinstance` str)

Tento zápis lze použít i při volání uživatelsky definované funkce, a to například takto:

def add(a, b):
    return a+b
 
print(add(1, 2))
print(1 `add` 2)
 
1 `add` 2 |> print

Výsledek transpřekladu do Pythonu bude vypadat takto:

# Compiled Coconut: -----------------------------------------------------------
 
def add(a, b):  #1 (line in Coconut source)
    return a + b  #2 (line in Coconut source)
 
 
print(add(1, 2))  #4 (line in Coconut source)
print((add)(1, 2))  #5 (line in Coconut source)
 
(print)((add)(1, 2))  #7 (line in Coconut source)

Podívejme se na poněkud složitější příklad s definicí funkce „n nad k“, kterou lze volat dvěma způsoby – jako klasickou funkci i v infixovém zápisu:

def factorial(n):
    if n <= 1:
        return 1
    else:
        return range(1, n+1) |> reduce$(*)
 
def choose(n, k):
    return factorial(n)/(factorial(k)*factorial(n-k))
 
print(factorial(10))
 
for k in range(5):
    print(choose(4, k))
 
print()
 
for k in range(5):
    print(4 `choose` k)

Transpřeklad obou funkcí do Pythonu bude vypadat následovně:

# Compiled Coconut: -----------------------------------------------------------
 
print((isinstance)("hello", str))  #1 (line in Coconut source)
 
@_coconut_tco  #3 (line in Coconut source)
def factorial(n):  #3 (line in Coconut source)
    if n &tt;= 1:  #4 (line in Coconut source)
        return 1  #5 (line in Coconut source)
    else:  #6 (line in Coconut source)
        return _coconut_tail_call((reduce), _coconut.operator.mul, range(1, n + 1))  #7 (line in Coconut source)
 
 
def choose(n, k):  #9 (line in Coconut source)
    return factorial(n) / (factorial(k) * factorial(n - k))  #10 (line in Coconut source)
 
 
print(factorial(10))  #12 (line in Coconut source)
 
for k in range(5):  #14 (line in Coconut source)
    print(choose(4, k))  #15 (line in Coconut source)
 
print()  #17 (line in Coconut source)
 
for k in range(5):  #19 (line in Coconut source)
    print((choose)(4, k))  #20 (line in Coconut source)

11. Infixový zápis při definici nových funkcí

Dokonce i při definici funkce, tedy nikoli pouze při jejím volání, je možné použít infixový zápis. Příkladem může být funkce pojmenovaná nad, kterou lze definovat dvěma zcela ekvivalentními způsoby, a to buď jako běžnou funkci (to již známe) nebo „infixovým“ způsobem:

factorial = n => reduce((a, b) => a*b, range(1, n+1), 1)
 
def n `nad` k:
    return factorial(n)/(factorial(k)*factorial(n-k))
 
for k in range(5):
    4 `nad` k |> print

Výsledek transpřekladu:

# Compiled Coconut: -----------------------------------------------------------
 
print((isinstance)("hello", str))  #1 (line in Coconut source)
 
factorial = lambda n: reduce(lambda a, b: a * b, range(1, n + 1), 1)  #3 (line in Coconut source)
 
def nad(n, k):  #5 (line in Coconut source)
    return factorial(n) / (factorial(k) * factorial(n - k))  #6 (line in Coconut source)
 
 
for k in range(5):  #8 (line in Coconut source)
    (print)((nad)(4, k))  #9 (line in Coconut source)

12. Priorita volání funkcí zapsaných infixovým způsobem

S „infixovým“ voláním funkcí, tj. s využitím funkcí ve výrazech tak, jakoby se jednalo o binární operátory, ještě pochopitelně souvisí otázka priority a asociativity. Priorita všech těchto volání je stejná a asociativita je nastavená zleva doprava. Samozřejmě ovšem můžeme s využitím běžných kulatých závorek prioritu měnit a nejprve zavolat funkci, která se ve výrazu vyskytuje více vpravo. Ostatně si to můžeme velmi snadno otestovat:

def add(a, b):
    return a+b
 
def mul(x, y):
    return x * y
 
1 `add` 2 `mul` 3 |> print
1 `add` (2 `mul` 3) |> print

Výsledky získané po spuštění tohoto skriptu ukazují, že v prvním případě se vyhodnotil výraz (1+2)*3 a ve druhém pak 1+(2*3):

9
7

Priorita je patrná i z transpilovaného kódu:

# Compiled Coconut: -----------------------------------------------------------
 
def add(a, b):  #1 (line in Coconut source)
    return a + b  #2 (line in Coconut source)
 
 
def mul(x, y):  #4 (line in Coconut source)
    return x * y  #5 (line in Coconut source)
 
 
(print)((mul)((add)(1, 2), 3))  #7 (line in Coconut source)
(print)((add)(1, ((mul)(2, 3))))  #8 (line in Coconut source)

13. Kompatibilita s Pythonem 2 a Pythonem 3

V jazyku Coconut je možné používat i klíčová slova a jazykové konstrukce, které byly zavedeny v některé verzi Pythonu 3 (ostatně tabulku s novinkami v jednotlivých variantách Pythonu jsme si již uvedli minule). Coconut použití těchto konstrukcí hlídá a v případě, že se pokusíme o transpilaci do Pythonu 2 (což je výchozí nastavení), odmítne tuto operaci provést, protože výsledek by nebyl použitelný. V takovém případě tedy musíme specifikovat přesnou (minimální) verzi Pythonu, se kterým bude transpilovaný zdrojový kód kompatibilní. Verze se nastavuje přepínačem -t nebo –target, přičemž v současnosti lze specifikovat tyto verze Pythonu (bez tečky):

2,
26,
27,
3,
32
33,
34,
35,
36,
37,
38,
39,
310,
311,
312,
313,

14. Kontrola verze Pythonu v runtime

Ve vygenerovaném Pythonovském kódu se některé knihovny, například asyncio (pro podporu konstrukcí async a await) importují pouze v případě, že je použita taková verze Pythonu, která tyto knihovny obsahuje. U starších verzí k importu nedojde a tudíž skript při svém spuštění zhavaruje. Takto zhruba vypadá kód, který podobný import provádí:

try:  #1 (line in Coconut source)
    _coconut_sys_0 = sys  # type: ignore  #1 (line in Coconut source)
except _coconut.NameError:  #1 (line in Coconut source)
    _coconut_sys_0 = _coconut_sentinel  #1 (line in Coconut source)
sys = _coconut_sys  #1 (line in Coconut source)
if sys.version_info >= (3, 4):  #1 (line in Coconut source)
    import asyncio  #1 (line in Coconut source)

15. Klíčová slova async a await

Rezervovaná klíčová slova async a await byla zavedena do Pythonu verze 3.7. Tato slova umožňují definici bloků, které budou spouštěny asynchronně, popř. naopak realizovat čekání na dokončení činnosti těchto bloků. Programovací jazyk Coconut dokáže s asynchronními bloky pracovat a navíc detekuje (viz předchozí text) detekovat, jestli cílová verze Pythonu tyto jazykové konstrukce podporuje či nikoli.

import asyncio
 
 
async def task():
    print("task started")
    await asyncio.sleep(5)
    print("task finished")
 
 
def main():
    task1 = asyncio.create_task(task())
    print("task created")
 
    await task1
 
    print("done")
 
 
main()

Tento prográmek bude transpilován do Pythonu následovně. Povšimněte si snahy o zajištění kompatibility i se staršími verzemi Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
try:  #1 (line in Coconut source)
    _coconut_sys_0 = sys  # type: ignore  #1 (line in Coconut source)
except _coconut.NameError:  #1 (line in Coconut source)
    _coconut_sys_0 = _coconut_sentinel  #1 (line in Coconut source)
sys = _coconut_sys  #1 (line in Coconut source)
if sys.version_info >= (3, 4):  #1 (line in Coconut source)
    import asyncio  #1 (line in Coconut source)
else:  #1 (line in Coconut source)
    import trollius as asyncio  #1 (line in Coconut source)
if _coconut_sys_0 is not _coconut_sentinel:  #1 (line in Coconut source)
    sys = _coconut_sys_0  #1 (line in Coconut source)
 
 
@_coconut.asyncio.coroutine  #4 (line in Coconut source)
def task():  #4 (line in Coconut source)
    print("task started")  #5 (line in Coconut source)
    (yield _coconut.asyncio.From(asyncio.sleep(5)))  #6 (line in Coconut source)
    print("task finished")  #7 (line in Coconut source)
 
 
 
    if False:  #10 (line in Coconut source)
        yield  #10 (line in Coconut source)
def main():  #10 (line in Coconut source)
    task1 = asyncio.create_task(task())  #11 (line in Coconut source)
    print("task created")  #12 (line in Coconut source)
 
    (yield _coconut.asyncio.From(task1))  #14 (line in Coconut source)
 
    print("done")  #16 (line in Coconut source)
 
 
 
main()  #19 (line in Coconut source)

16. Nelokální proměnné

Aby bylo možné v jazyku Python vytvářet plnohodnotné uzávěry s modifikovatelným prostředím (environment), bylo do verze 3.x přidáno nové klíčové slovo nonlocal. Tímto klíčovým slovem je možné ve vnitřní funkci – tedy ve vlastním „jádru“ uzávěru – označit proměnnou, která nemá být chápána jako proměnná lokální, ale ke které chceme přistupovat (a potenciálně ji i měnit). V Pythonu 2 lze sice podobného chování dosáhnout také, ale je nutné využívat různých triků (proměnná bude typu seznam či slovník atd.). Ovšem nyní nás bude zajímat především použití klíčového slova nonlocal. Využijeme ho pro naprogramování čítače (čítačů) realizovaného uzávěrem:

def createCounter():
    counter = 0
    def nextValue():
        nonlocal counter
        counter += 1
        return counter
    return nextValue
 
 
 
def main():
    counter1 = createCounter()
    counter2 = createCounter()
    for i in range(1,11):
        result1 = counter1()
        result2 = counter2()
        print("Iteration #%d" % i)
        print("    Counter1: %d" % result1)
        print("    Counter2: %d" % result2)
 
 
main()

Bez použití nonlocal by interpret ohlásil chybu při pokusu o přístupu k neinicializované lokální proměnné. Tento skript, což je mimochodem plnohodnotný skript napsaný v jazyce Coconut, bude přeložitelný pouze do Pythonu verze 3 a nikoli verze 2.

17. Mroží operátor

Další vlastností, která je v Coconutu podporována pouze za předpokladu, že se provádí transpřeklad do Pythonu 3 (konkrétně do verze 3.8 a vyšší), je takzvaný mroží operátor. Tento název vychází z vizuální podoby tohoto operátoru, který se zapisuje dvojicí znaků := (jde tedy o smajlík, který při troše fantazie připomíná mroží kly). Přesný popis syntaxe a zejména sémantiky tohoto operátoru nalezneme v dokumentu PEP 572 – Assignment Expressions. Mroží operátor umožňuje provést přiřazení v rámci výrazu (expression), což v důsledku znamená, že se jedná o rozšíření Pythonu, protože před zavedením mrožího operátoru se přiřazení provádělo jen v rámci příkazu (statement). Zjednodušeně řečeno: operace přiřazení sama o sobě byla příkazem, a to i v případě, že se hodnota přiřazovala do většího množství proměnných (definice přiřazení je rekurzivní).

Ukažme si příklad, ve kterém je patrné, že mroží operátor může být skutečně užitečný:

values = (1, 2, 3, 4, 5)
 
result = {
        "count": (count := len(values)),
        "sum": (summ := sum(values)),
        "mean": summ/count
        }
 
print(result)

Opět platí, že překlad z Coconutu (protože výše uvedený skript je napsán i v tomto jazyce) se přeloží jen ve chvíli, kdy zvolíme jako cílový Python verzi 3.8 či novější.

Výsledek transpřekladu z jazyka Coconut do Pythonu dopadne následovně:

ict ve školství 24

# Compiled Coconut: -----------------------------------------------------------
 
values = (1, 2, 3, 4, 5)  #1 (line in Coconut source)
 
result = _coconut.dict((("count", (count := len(values))), ("sum", (summ := sum(values))), ("mean", summ / count)))  #3 (line in Coconut source)
 
print(result)  #9 (line in Coconut source)

18. Obsah navazujícího článku

Pravděpodobně nejdůležitější vlastností programovacího jazyka Coconut je podpora pro pokročilý pattern matching. Tento koncept se sice objevil i ve standardním Pythonu (viz též článek Nejdůležitější novinka v Pythonu 3.10: strukturální pattern matching), ovšem v Coconutu se jedná o pokročilejší techniku umožňující zápis takových vzorů, které Python nepodporuje. A to není vše, protože pattern matching je možné v jazyku Coconut použít například i přímo při definici funkce, což je konstrukce evidentně inspirovaná v jazycích z rodiny ML (Standard ML, CAML, OCaml, F#). Tímto tématem se budeme podrobněji zabývat příště.

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

Zdrojové kódy všech prozatím popsaných demonstračních příkladů určených pro programovací jazyk Coconut byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs.

# Příklad Stručný popis Adresa
1 hello-world.coco Program typu „Hello, world“ naprogramovaný v jazyce Coconut https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/hello-world.coco
2 hello-world.py překlad pipeline s voláním funkce print do Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/hello-world.py
3 hello-world-non-optim.py ukázka celého souboru (čistý Python), který vznikne výsledkem transpřekladu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/hello-world-non-optim.py
4 hello-world-minified.py ukázka celého souboru (čistý Python), který vznikne výsledkem transpřekladu s povolenou minifikací https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/hello-world-minified.py
       
5 lambda-old-style.coco zápis anonymní funkce s využitím operátoru → (původní styl Pythonu) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-old-style.coco
6 lambda-old-style.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-old-style.py
7 lambda-new-style.coco zápis anonymní funkce s využitím operátoru ⇒ (doporučovaný styl) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-new-style.coco
8 lambda-new-style.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-new-style.py
       
9 original-factorial-1.py výpočet faktoriálu naprogramovaný v Pythonu: použití anonymní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/original-factorial-1.py
10 original-factorial-2.py výpočet faktoriálu naprogramovaný v Pythonu: vnořené anonymní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/original-factorial-2.py
11 original-factorial-3.py výpočet tabulky s faktoriály bez použití programových smyček https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/original-factorial-3.py
       
12 lambda-factorial-1.coco výpočet faktoriálu s anonymní funkcí se dvěma parametry (nekorektní zápis) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-1.coco
13 lambda-factorial-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-1.py
14 lambda-factorial-2.coco výpočet faktoriálu s anonymní funkcí se dvěma parametry (korektní zápis) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-2.coco
15 lambda-factorial-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-2.py
16 lambda-factorial-3.coco vnořené anonymní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-3.coco
17 lambda-factorial-3.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-3.py
18 lambda-factorial-4.coco výpočet tabulky s faktoriály bez použití programových smyček https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-4.coco
19 lambda-factorial-4.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-4.py
20 lambda-factorial-5.coco výpočet tabulky s faktoriály bez použití programových smyček + použití pipe https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-5.coco
21 lambda-factorial-5.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/lambda-factorial-5.py
       
22 implicit-lambda-1.coco lambda výraz s implicitním parametrem https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/implicit-lambda-1.coco
23 implicit-lambda-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/implicit-lambda-1.py
24 implicit-lambda-2.coco lambda výraz bez parametru https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/implicit-lambda-2.coco
25 implicit-lambda-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/implicit-lambda-2.py
       
26 statement-lambda-1.coco plnohodnotná anonymní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-1.coco
27 statement-lambda-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-1.py
28 statement-lambda-2.coco anonymní funkce s příkazem a výrazem https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-2.coco
29 statement-lambda-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-2.py
       
30 statement-lambda-type-hints.coco anonymní funkce s typovými informacemi https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-type-hints.coco
31 statement-lambda-type-hints-python-2.py výsledek překladu skriptu do standardního Pythonu verze 2 https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-type-hints-python-2.py
32 statement-lambda-type-hints-python-3.py výsledek překladu skriptu do standardního Pythonu verze 3 https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/statement-lambda-type-hints-python-3.py
       
33 original-partial-1.py částečně vyhodnocená funkce, realizace provedená ve standardním Pythonu, první verze (funkce se dvěma parametry) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/original-partial-1.py
34 original-partial-2.py částečně vyhodnocená funkce, realizace provedená ve standardním Pythonu, druhá verze (funkce se třemi parametry) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/original-partial-2.py
35 original-partial-3.py částečně vyhodnocená funkce, realizace provedená ve standardním Pythonu, třetí verze (funkce se čtyřmi parametry) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/original-partial-3.py
       
36 partial-1.coco částečně vyhodnocená funkce zapsaná v jazyku Coconut, první verze (funkce se dvěma parametry) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-1.coco
37 partial-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-1.py
38 partial-2.coco částečně vyhodnocená funkce zapsaná v jazyku Coconut, druhá verze (funkce se třemi parametry) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-2.coco
39 partial-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-2.py
40 partial-3.coco částečně vyhodnocená funkce zapsaná v jazyku Coconut, třetí verze (funkce se čtyřmi parametry) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-3.coco
41 partial-3.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-3.py
       
42 partial-map.coco částečně vyhodnocená funkce vyššího řádu fmap https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-map.coco
43 partial-map.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/partial-map.py
       
44 sequences1A.coco ukázka rozdílu v chování funkcí map a fmap https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences1A.coco
45 sequences1A.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences1A.py
46 sequences1B.coco přepis předchozího demonstračního příkladu tak, že se využije zkrácený zápis lambda výrazů https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences1B.coco
47 sequences1B.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences1B.py
48 sequences1C.coco přepis předchozího demonstračního příkladu tak, že se využije zkrácený zápis lambda výrazů s implicitním parametrem https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences1C.coco
49 sequences1C.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences1C.py
50 sequences2A.coco ukázka funkcí reduce, takewhile a dropwhile https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences2A.coco
51 sequences2A.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences2A.py
52 sequences2B.coco přepis předchozího demonstračního příkladu tak, že se využije zkrácený zápis lambda výrazů https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences2B.coco
53 sequences2B.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences2B.py
54 sequences2C.coco přepis předchozího demonstračního příkladu tak, že se využije zkrácený zápis lambda výrazů s implicitním parametrem https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences2C.coco
55 sequences2C.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/se­quences2C.py
       
56 custom-operator-1.coco vytvoření nového binárního operátoru https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/custom-operator-1.coco
57 custom-operator-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/custom-operator-1.py
58 custom-operator-2.coco vytvoření nového binárního operátoru https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/custom-operator-2.coco
59 custom-operator-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/custom-operator-2.py
60 custom-operator-3.coco vytvoření nového unárního operátoru https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/custom-operator-3.coco
61 custom-operator-3.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/custom-operator-3.py
       
62 infix-notation-1.coco infixový zápis volání funkce add https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-1.coco
63 infix-notation-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-1.py
64 infix-notation-2.coco infixový zápis volání funkce factorial https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-2.coco
65 infix-notation-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-2.py
66 infix-notation-3.coco infixová definice funkce nad https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-3.coco
67 infix-notation-3.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-3.py
68 infix-notation-4.coco infixový zápis volání funkcí a priorita operací https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-4.coco
69 infix-notation-4.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/infix-notation-4.py
       
70 py3-only-async-await.coco konstrukce platná pouze v Pythonu 3.x – asyncawait https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/py3-only-async-await.coco
71 py3-only-async-await.py výsledek překladu skriptu do standardního Pythonu verze 3.x https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/py3-only-async-await.py
72 py3-only-counter_closure.coco konstrukce platná pouze v Pythonu 3.x – nelokální proměnná https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/py3-only-counter_closure.coco
73 py3-only-counter_closure.py výsledek překladu skriptu do standardního Pythonu verze 3.x https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/py3-only-counter_closure.py
74 py3-only-walrus-operator.coco konstrukce platná pouze v Pythonu 3.x – mroží operátor https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/py3-only-walrus-operator.coco
75 py3-only-walrus-operator.py výsledek překladu skriptu do standardního Pythonu verze 3.x https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/py3-only-walrus-operator.py

20. Odkazy na Internetu

  1. Coconut: funkcionální jazyk s pattern matchingem kompatibilní s Pythonem
    https://www.root.cz/clanky/coconut-funkcionalni-jazyk-s-pattern-matchingem-kompatibilni-s-pythonem/
  2. Coconut aneb funkcionální nadstavba nad Pythonem (2.část)
    https://www.root.cz/clanky/coconut-aneb-funkcionalni-nadstavba-nad-pythonem-2-cast/
  3. Python 3.10 and the Elegance of Pattern Matching
    https://python.plainenglish.io/python-3–10-and-the-elegance-of-pattern-matching-2620a02b2379
  4. More Pattern Matching in Python 3.10
    https://towardsdatascience.com/more-advanced-pattern-matching-in-python-3–10–2dbd8598302a
  5. Pattern Matching in Python 3.10
    https://towardsdatascience.com/pattern-matching-in-python-3–10–6124ff2079f0
  6. Python 3.10.0
    https://www.python.org/dow­nloads/release/python-3100/
  7. The fate of reduce() in Python 3000
    http://lambda-the-ultimate.org/node/587
  8. PEP 634 – Structural Pattern Matching: Specification
    https://peps.python.org/pep-0634/
  9. PEP 635 – Structural Pattern Matching: Motivation and Rationale
    https://peps.python.org/pep-0635/
  10. PEP 636 – Structural Pattern Matching: Tutorial
    https://peps.python.org/pep-0636/
  11. PEP 622 – Structural Pattern Matching
    https://peps.python.org/pep-0622/
  12. Python 3.10 se strukturálním pattern matchingem
    https://www.root.cz/zpravicky/python-3–10-se-strukturalnim-pattern-matchingem/
  13. Null coalescing operator
    https://en.wikipedia.org/wi­ki/Null_coalescing_operator
  14. Operátor koalescence
    https://cs.wikipedia.org/wi­ki/Oper%C3%A1tor_koalescen­ce
  15. Elvis operator
    https://en.wikipedia.org/wi­ki/Elvis_operator
  16. Safe navigation operator
    https://en.wikipedia.org/wi­ki/Safe_navigation_operator
  17. Setting stacksize in a python script
    https://stackoverflow.com/qu­estions/5061582/setting-stacksize-in-a-python-script
  18. What is the maximum recursion depth in Python, and how to increase it?
    https://stackoverflow.com/qu­estions/3323001/what-is-the-maximum-recursion-depth-in-python-and-how-to-increase-it?rq=1
  19. Does Python optimize tail recursion?
    https://stackoverflow.com/qu­estions/13591970/does-python-optimize-tail-recursion
  20. Programovací jazyk APL: programování bez smyček
    https://www.root.cz/clanky/pro­gramovaci-jazyk-apl-programovani-bez-smycek/
  21. Programovací jazyk APL – dokončení
    https://www.root.cz/clanky/pro­gramovaci-jazyk-apl-dokonceni/
  22. Tail call
    https://en.wikipedia.org/wi­ki/Tail_call
  23. Tail Call Optimization for Python
    https://github.com/baruchel/tco
  24. Tail Recursion Elimination
    http://neopythonic.blogspot­.cz/2009/04/tail-recursion-elimination.html
  25. Origins of Python's „Functional“ Features
    http://python-history.blogspot.cz/2009/04/origins-of-pythons-functional-features.html
  26. Tail recursion decorator revisited
    http://fiber-space.de/wordpress/2009/04/20/tail-recursion-decorator-revisited/
  27. Koncová rekurze
    https://cs.wikipedia.org/wi­ki/Koncov%C3%A1_rekurze
  28. Recursion (computer science)
    https://en.wikipedia.org/wi­ki/Recursion_%28computer_sci­ence%29
  29. Coconut: Simple, elegant, Pythonic functional programming
    http://coconut-lang.org/
  30. coconut 1.1.0 (Python package index)
    https://pypi.python.org/py­pi/coconut/1.1.0
  31. Coconut Tutorial
    http://coconut.readthedoc­s.io/en/master/HELP.html
  32. Coconut FAQ
    http://coconut.readthedoc­s.io/en/master/FAQ.html
  33. Coconut Documentation
    http://coconut.readthedoc­s.io/en/master/DOCS.html
  34. Python gains functional programming syntax via Coconut
    https://www.infoworld.com/ar­ticle/3088058/python-gains-functional-programming-syntax-via-coconut.html
  35. Repositář projektu pyparsing
    https://github.com/pyparsin­g/pyparsing
  36. Repositář projektu cPyparsing
    https://github.com/evhub/cpyparsing
  37. Projekty vylepšující interaktivní režim Pythonu: bpython, ptpython, DreamPie a IPython
    https://www.root.cz/clanky/projekty-vylepsujici-interaktivni-rezim-pythonu-bpython-ptpython-dreampie-a-ipython/
  38. Coconut na Redditu
    https://www.reddit.com/r/Pyt­hon/comments/4owzu7/coconut_fun­ctional_programming_in_pyt­hon/
  39. Repositář na GitHubu
    https://github.com/evhub/coconut
  40. patterns
    https://github.com/Suor/patterns
  41. Source-to-source compiler
    https://en.wikipedia.org/wiki/Source-to-source_compiler
  42. The Lua VM, on the Web
    https://kripken.github.io/lu­a.vm.js/lua.vm.js.html
  43. Lua.vm.js REPL
    https://kripken.github.io/lu­a.vm.js/repl.html
  44. lua2js
    https://www.npmjs.com/package/lua2js
  45. Wisp na GitHubu
    https://github.com/Gozala/wisp
  46. Wisp playground
    http://www.jeditoolkit.com/try-wisp/
  47. REPL v prohlížeči
    http://www.jeditoolkit.com/in­teractivate-wisp/
  48. Minification (programming)
    https://en.wikipedia.org/wi­ki/Minification_(programmin­g)
  49. JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML
    http://www.hanselman.com/blog/Ja­vaScriptIsAssemblyLanguage­ForTheWebSematicMarkupIsDe­adCleanVsMachinecodedHTML­.aspx
  50. JavaScript is Web Assembly Language and that's OK.
    http://www.hanselman.com/blog/Ja­vaScriptIsWebAssemblyLangu­ageAndThatsOK.aspx
  51. Dart
    https://www.dartlang.org/
  52. CoffeeScript
    http://coffeescript.org/
  53. TypeScript
    http://www.typescriptlang.org/
  54. JavaScript: The Web Assembly Language?
    http://www.informit.com/ar­ticles/article.aspx?p=1856657
  55. asm.js
    http://asmjs.org/
  56. List of languages that compile to JS
    https://github.com/jashke­nas/coffeescript/wiki/List-of-languages-that-compile-to-JS
  57. Permutation
    https://en.wikipedia.org/wi­ki/Permutation
  58. Pattern matching (Wikipedia)
    https://en.wikipedia.org/wi­ki/Pattern_matching
  59. Pattern matching v Rustu
    https://www.root.cz/clanky/rust-funkce-lambda-vyrazy-a-rozhodovaci-konstrukce-match/#k13
  60. SNOBOL
    https://en.wikipedia.org/wiki/SNOBOL
  61. Podpůrný plugin pro Vim
    https://github.com/manicma­niac/coconut.vim
  62. Příkaz (programování)
    https://cs.wikipedia.org/wi­ki/P%C5%99%C3%ADkaz_%28pro­gramov%C3%A1n%C3%AD%29
  63. Threading Macros Guide
    https://clojure.org/guides/thre­ading_macros
  64. Nejdůležitější novinka v Pythonu 3.10: strukturální pattern matching
    https://www.root.cz/clanky/nej­dulezitejsi-novinka-v-pythonu-3–10-strukturalni-pattern-matching/
ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

Autor článku

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