Konstrukce kolon a kompozice funkcí v jazyku Coconut

13. 6. 2024
Doba čtení: 39 minut

Sdílet

 Autor: Depositphotos
Pipeline je v současném IT jedno z nejzneužívanějších slov. V jazyku Coconut lze pipeline používat ve smyslu kolon, tedy pro zajištění předávání návratových hodnot funkcí do jiných funkcí, což je základ tacit programmingu.

Obsah

1. Konstrukce kolony v jazyku Coconut

2. Způsob transpřekladu příkazů s kolonou z Coconutu do Pythonu

3. Další typy operátorů pro konstrukci kolon

4. Kolona, ve které data proudí opačným směrem

5. Kolony a problematika hodnoty None

6. Kolony rozpoznávající hodnotu None

7. Operátor |?>

8. Vynucení výpisu výsledku, který je produkován kolonou

9. Operátor <?|

10. Poslání většího množství hodnot kolonou

11. Kolona umožňující posílání více hodnot současně

12. Standardní či uživatelský operátor v koloně

13. Kolona s funkcemi, do kterých se předávají keyword parametry

14. Kompozice funkcí

15. Ukázka kompozice funkcí operátorem ..

16. Uložení výsledku kompozice funkcí do proměnné – konstrukce nové funkce

17. Další operátory realizující odlišné způsoby kompozice funkcí

18. Alternativní způsob zápisu operátoru ..

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

20. Odkazy na Internetu

1. Konstrukce kolony v jazyku Coconut

V programovacím jazyku Coconut nalezneme velmi užitečnou technologii. Jedná se o možnost vytvoření takzvané kolony (pipeline) z funkcí, což je technologie, kterou velmi pravděpodobně znáte z shellu, ale najdeme ji například i v programovacím jazyku Clojure (threading macro), v programovacích jazycích z rodiny ML apod. Základní kolona se sestaví operátorem |>, který dokáže poslat data ze své levé strany do funkce uvedené na straně pravé. V případě, že taková funkce vrací jiná data, je samozřejmě možné kolonu libovolným způsobem rozšiřovat. Nejprve si ukážeme to nejjednodušší použití kolony pro funkce s jediným vstupem:

-42 |> abs |> print
 
"B" |> ord |> abs |> hex |> print
 
range(11) |> sum |> print
 
range(11) |> reversed |> sum |> print
 
def evens(sequence):
    return filter(lambda x: x % 2 == 0, sequence)
 
[1, 2, 3, 4, 5, 6, 30] |> evens |> sum |> print
Poznámka: povšimněte si, že posledním identifikátorem na pravé straně kolony je vždy funkce a nikoli proměnná.
Poznámka: zápis operátoru |> není specialitou programovacího jazyka Coconut. Prakticky stejný operátor (tedy stejný ve smyslu syntaxe i sémantiky) nalezneme například v programovacím jazyku F#, s nímž jsme se seznámili v tomto seriálu. Připomeňme si, že v F# bylo možné počtem znaků | naznačit, kolik hodnot se předává (následující blok můžete ignorovat; týkají se typového systému jazyka F#):
> ( ||> );;
val it: ('a * 'b -> ('a -> 'b -> 'c) -> 'c)
 
> ( |||> );;
val it: ('a * 'b * 'c -> ('a -> 'b -> 'c -> 'd) -> 'd)
  
> ( <|| );;
val it: (('a -> 'b -> 'c) -> 'a * 'b -> 'c)
  
> ( <||| );;
val it: (('a -> 'b -> 'c -> 'd) -> 'a * 'b * 'c -> 'd)

2. Způsob transpřekladu příkazů s kolonou z Coconutu do Pythonu

Z transpilovaného výsledku je patrné, jakým způsobem se použití kolony přeloží do čistého Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
(print)((abs)(-42))  #1 (line in Coconut source)
 
(print)((hex)((abs)((ord)("B"))))  #3 (line in Coconut source)
 
(print)((sum)(range(11)))  #5 (line in Coconut source)
 
(print)((sum)((reversed)(range(11))))  #7 (line in Coconut source)
 
@_coconut_tco  #9 (line in Coconut source)
def evens(sequence):  #9 (line in Coconut source)
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)  #10 (line in Coconut source)
 
 
(print)((sum)((evens)([1, 2, 3, 4, 5, 6, 30])))  #12 (line in Coconut source)

Podívejme se však na zjednodušenou podobu transpilovaného kódu, ze které byly odstraněny nadbytečné závorky. Nyní je výsledek mnohem čitelnější a ukazuje roli kolony jakožto konstrukce nahrazující volání funkcí při předávání parametrů do jiných funkcí:

# Simplified version of Coconut transpiled into Python
 
print(abs(-42))
 
print(hex(abs(ord("B"))))
 
print(sum(range(11)))
 
print(sum(reversed(range(11))))
 
 
@_coconut_tco
def evens(sequence):
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)
 
 
print(sum(evens([1, 2, 3, 4, 5, 6, 30])))

3. Další typy operátorů pro konstrukci kolon

Základní kolona realizovaná operátorem |> je ve skutečnosti pouze jedním typem kolony podporované programovacím jazykem Coconut. Vývojáři totiž mají k dispozici hned několik dalších operátorů pro konstrukci kolony, které se od sebe liší směrem proudění dat (zleva doprava nebo zprava doleva), tím, zda dokážou rozpoznat hodnoty None a patřičně na ně zareagovat a v neposlední řadě i podle toho, zda se přenáší vždy jediná hodnota nebo větší množství hodnot (což ovšem vyžaduje korektní uzávorkování). Všechny v současnosti dostupné operátory kolony nalezneme v následující tabulce:

# Operátor Směr proudění dat Zpracování None Poznámka
1 |> zleva doprava ne přenos jedné hodnoty
2 |*> zleva doprava ne přenos více hodnot
3 |**> zleva doprava ne přenos hodnot přes keyword argumenty
         
4 <| zprava doleva ne přenos jedné hodnoty
5 <*| zprava doleva ne přenos více hodnot
6 <**| zprava doleva ne přenos hodnot přes keyword argumenty
         
7 |?> zleva doprava ano přenos jedné hodnoty
8 |?*> zleva doprava ano přenos více hodnot
9 |?**> zleva doprava ano přenos hodnot přes keyword argumenty
         
10 <?| zprava doleva ano přenos jedné hodnoty
11 <*?| zprava doleva ano přenos více hodnot
12 <**?| zprava doleva ano přenos hodnot přes keyword argumenty
Poznámka: kombinace vlastností operátorů se odráží i na způsobu jejich zápisu, který je logický a „ortogonální“ a tedy relativně dobře zapamatovatelný.

Některé z výše uvedených možností konstrukce kolon budou popsány v navazujících kapitolách.

4. Kolona, ve které data proudí opačným směrem

Nejprve se podívejme na tvorbu kolony s využitím operátoru <|. Jedná se o obdobu základního operátoru |>, ovšem s jedním podstatným rozdílem: data budou v tomto případě přenášena zprava doleva. To jinými slovy znamená, že zdroj dat (což může být konstanta, funkce, metoda, ale například i konstruktor) bude zapsán zcela napravo a postupné cíle dat budou zapsány nalevo od tohoto zdroje.

Ukažme si toto chování na dvou příkazech, přičemž je dobré si povšimnout toho, že ve druhém příkazu je nutné provést uzávorkování. Je tomu tak z toho důvodu, že samotný operátor <| se vyhodnocuje zleva doprava, ostatně podobně, jako je tomu u ostatních jedenácti operátorů pro realizaci kolon.

print <| -42
 
print <| (abs <| -42)

Výsledek transpilace:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(-42)  #1 (line in Coconut source)
 
(print)(((abs)(-42)))  #3 (line in Coconut source)

Následuje zjednodušená varianta, která lépe ukazuje, jak se kolona přeloží:

# Simplified version of Coconut transpiled into Python
 
print(-42)
 
print(abs(-42))

5. Kolony a problematika hodnoty None

Pokusme se nyní do kolony předat hodnotu None a sledovat, jak bude tato hodnota celou kolonou „probublávat“. Nejprve použijeme původní operátor |>, který se nijak nesnaží o detekci této hodnoty:

None |> print
 
None |> abs |> print
  
None |> ord |> abs |> hex |> print
 
None |> sum |> print
 
None |> reversed |> sum |> print
 
def evens(sequence):
    return filter(lambda x: x % 2 == 0, sequence)
 
None |> evens |> sum |> print

Skript si necháme (trans)přeložit a ihned spustit:

$ coconut -r pipeline-none-not-aware.coco

První příkaz byl spuštěn a vykonán bez problémů, protože standardní funkce print pochopitelně dokáže hodnotu None vytisknout, ale už u následujícího příkazu došlo k běhové chybě při pokusu o předání hodnoty None do funkce abs:

Compiling         pipeline-none-not-aware.coco ...
CoconutWarning: Populating initial parsing cache (compilation may take longer than usual)...
Compiled to       pipeline-none-not-aware.py .
None
Traceback (most recent call last):
  File "<frozen runpy>", line 291, in run_path
  File "<frozen runpy>", line 98, in _run_module_code
  File "<frozen runpy>", line 88, in _run_code
  File "/home/ptisnovs/xy/pipeline-none-not-aware.py", line 2902, in <module>
    (print)((abs)(None))  #3 (line in Coconut source)
            ^^^^^^^^^^^
TypeError: bad operand type for abs(): 'NoneType'

Důvod pádu je zřejmý a zjistíme ho při pohledu na transpilovaný zdrojový kód. Nejprve originál vygenerovaný Coconutem:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(None)  #1 (line in Coconut source)
 
(print)((abs)(None))  #3 (line in Coconut source)
 
(print)((hex)((abs)((ord)(None))))  #5 (line in Coconut source)
 
(print)((sum)(None))  #7 (line in Coconut source)
 
(print)((sum)((reversed)(None)))  #9 (line in Coconut source)
 
@_coconut_tco  #11 (line in Coconut source)
def evens(sequence):  #11 (line in Coconut source)
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)  #12 (line in Coconut source)
 
 
(print)((sum)((evens)(None)))  #14 (line in Coconut source)

Následuje upravený (zjednodušený) kód, který je sémanticky naprosto totožný s kódem předchozím:

# Simplified version of Coconut transpiled into Python
 
print(None)
 
print(abs(None))
 
print(hex(abs(ord(None))))
 
print(sum(None))
 
print(sum(reversed(None)))
 
@_coconut_tco
def evens(sequence):
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)
 
 
print(sum(evens(None)))

6. Kolony rozpoznávající hodnotu None

V praxi se poměrně často setkáme se situací, kdy do kolony mohou proudit hodnoty None. V případě, že tyto hodnoty považujeme za reprezentaci chybějící hodnoty (což je ostatně původní význam nil, ze kterého None vzniklo), budeme mnohdy chtít zajistit následující funkcionalitu:

  1. Běžné hodnoty rozdílné od None kolonou projdou a budou postupně zpracovány
  2. Pokud do kolony pošleme hodnotu None, zpracování se přeruší a ihned se taktéž vrátí hodnota None
  3. Pokud přímo v koloně vznikne hodnota None, bude opět ihned vrácena a zbytek kolony se přeskočí
Poznámka: takové chování do značné míry odpovídá typům Maybe, Result atd. (tyto typy se jmenují různě podle použitého programovacího jazyka).

7. Operátor |?>

Pro konstrukci kolony, která dokáže detekovat hodnotu None a patřičně na ni zareagovat, slouží operátor zapisovaný symboly |?>. Tento operátor má – až na zmíněnou schopnost detekovat hodnotu None – podobnou funkci a tedy i podobu, jako operátor |> popsaný v první části dnešního článku: hodnota je předávaná zleva doprava. Vyzkoušejme si tedy, předání hodnoty None do kolony:

None |?> print
 
None |?> abs |?> print
 
None |?> ord |?> abs |?> hex |?> print
 
None |?> sum |?> print
 
None |?> reversed |?> sum |?> print
 
def evens(sequence):
    return filter(lambda x: x % 2 == 0, sequence)
 
None |?> evens |?> sum |?> print

V případě, že tento skript spustíme, nevypíše se na standardní výstup žádná zpráva. Je tomu tak z toho důvodu, že hned na začátku pipeline je detekována hodnota None a zbytek pipeline je přeskočen, a to včetně funkce print na jejím konci. Je to ostatně patrné i při pohledu na transpilovaný kód:

# Compiled Coconut: -----------------------------------------------------------
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))(None)  #1 (line in Coconut source)
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (abs)(_coconut_x))(None))  #3 (line in Coconut source)
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (hex)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (abs)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (ord)(_coconut_x))(None))))  #5 (line in Coconut source)
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (sum)(_coconut_x))(None))  #7 (line in Coconut source)
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (sum)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (reversed)(_coconut_x))(None)))  #9 (line in Coconut source)
 
@_coconut_tco  #11 (line in Coconut source)
def evens(sequence):  #11 (line in Coconut source)
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)  #12 (line in Coconut source)
 
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (sum)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (evens)(_coconut_x))(None)))  #14 (line in Coconut source)

Zjednodušená podoba téhož kódu:

# Simplified version of Coconut transpiled into Python
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))(None)
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else abs(_coconut_x))(None))
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else hex(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else abs(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else ord(_coconut_x))(None))))
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else sum(_coconut_x))(None))
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else sum(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else reversed(_coconut_x))(None)))
 
@_coconut_tco
def evens(sequence):
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)
 
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else sum(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else evens(_coconut_x))(None)))

8. Vynucení výpisu výsledku, který je produkován kolonou

Pokud budeme chtít vypsat výsledek, který je kolonou produkován, a to za všech okolností, není možné ponechat volání funkce print na konci kolony, ale musíme použít určitý hybrid mezi kolonou a voláním funkce. Jedno z možných řešení bude vypadat následovně (a bude pochopitelně funkční pro všechny vstupy, nejenom pro None):

print(None |?> abs)
  
print(None |?> ord |?> abs |?> hex)
 
print(None |?> sum)
 
print(None |?> reversed |?> sum)
 
def evens(sequence):
    return filter(lambda x: x % 2 == 0, sequence)
 
print(None |?> evens |?> sum)

Skript si necháme transpilovat, výsledek spustíme a podle očekávání se vypíše několik stejných hodnot None:

None
None
None
None
None

Takto vypadá výsledek transpilace:

# Compiled Coconut: -----------------------------------------------------------
 
print((lambda _coconut_x: None if _coconut_x is None else (abs)(_coconut_x))(None))  #1 (line in Coconut source)
 
print((lambda _coconut_x: None if _coconut_x is None else (hex)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (abs)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (ord)(_coconut_x))(None))))  #3 (line in Coconut source)
 
print((lambda _coconut_x: None if _coconut_x is None else (sum)(_coconut_x))(None))  #5 (line in Coconut source)
 
print((lambda _coconut_x: None if _coconut_x is None else (sum)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (reversed)(_coconut_x))(None)))  #7 (line in Coconut source)
 
@_coconut_tco  #9 (line in Coconut source)
def evens(sequence):  #9 (line in Coconut source)
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)  #10 (line in Coconut source)
 
 
print((lambda _coconut_x: None if _coconut_x is None else (sum)(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else (evens)(_coconut_x))(None)))  #12 (line in Coconut source)

Tentýž zdrojový kód, ovšem po odstranění přebytečných závorek vkládaných transpilerem:

# Simplified version of Coconut transpiled into Python
 
print((lambda _coconut_x: None if _coconut_x is None else abs(_coconut_x))(None))
 
print((lambda _coconut_x: None if _coconut_x is None else hex(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else abs(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else ord(_coconut_x))(None))))
 
print((lambda _coconut_x: None if _coconut_x is None else sum(_coconut_x))(None))
 
print((lambda _coconut_x: None if _coconut_x is None else sum(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else reversed(_coconut_x))(None)))
 
@_coconut_tco
def evens(sequence):
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)
 
 
print((lambda _coconut_x: None if _coconut_x is None else sum(_coconut_x))((lambda _coconut_x: None if _coconut_x is None else evens(_coconut_x))(None)))

9. Operátor <?|

Známe již rozdíl mezi operátory |> a <|. A taktéž víme, jak se operátor |> odlišuje od operátoru |?>. Z těchto informací si můžeme snadno odvodit chování čtvrtého operátoru pro tvorbu kolony, tedy konkrétně operátoru zapisovaného znaky <?|. Tento operátor lze použít pro konstrukci kolony, v níž budou data proudit zprava doleva a přitom ve chvíli, kdy se detekuje hodnota None, kolona se přeruší a přímo se vrátí tato hodnota.

Nejprve si ovšem ověřme chování operátoru <| (bez otazníku) ve chvíli, kdy kolonou proudí hodnota None:

print <| None
 
print <| (abs <| None)
$ coconut -r --force pipeline-backward-none-not-aware.coco

První hodnota None se sice bez problémů vypíše, ale druhá kolona zhavaruje:

Compiling         pipeline-backward-none-not-aware.coco ...
CoconutWarning: Populating initial parsing cache (compilation may take longer than usual)...
Compiled to       pipeline-backward-none-not-aware.py .
None
Traceback (most recent call last):
  File "<frozen runpy>", line 291, in run_path
  File "<frozen runpy>", line 98, in _run_module_code
  File "<frozen runpy>", line 88, in _run_code
  File "/home/ptisnovs/xy/pipeline-backward-none-not-aware.py", line 2902, in
    (print)(((abs)(None)))  #3 (line in Coconut source)
             ^^^^^^^^^^^
TypeError: bad operand type for abs(): 'NoneType'

Proč tomu tak je, si lze velmi snadno ověřit v transpilovaném kódu:

# Compiled Coconut: -----------------------------------------------------------
 
(print)(None)  #1 (line in Coconut source)
 
(print)(((abs)(None)))  #3 (line in Coconut source)

resp.:

# Simplified version of Coconut transpiled into Python
 
print(None)
 
print((abs(None)))

V takovém případě nám pomůže právě operátor <?|, který dokáže hodnoty None detekovat a korektně na ně zareagovat přerušením běhu kolony:

print <?| None
 
print <?| (abs <?| None)

Opět si pro úplnost uveďme transpilovanou verzi:

# Compiled Coconut: -----------------------------------------------------------
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))(None)  #1 (line in Coconut source)
 
(lambda _coconut_x: None if _coconut_x is None else (print)(_coconut_x))(((lambda _coconut_x: None if _coconut_x is None else (abs)(_coconut_x))(None)))  #3 (line in Coconut source)

Zjednodušená podoba transpilované verze:

# Simplified version of Coconut transpiled into Python
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))(None)
 
(lambda _coconut_x: None if _coconut_x is None else print(_coconut_x))(((lambda _coconut_x: None if _coconut_x is None else abs(_coconut_x))(None)))

10. Poslání většího množství hodnot kolonou

Zbývá nám popis čtyř typů operátorů určených pro konstrukci kolony. Bude se jednat o operátory, které umožní předávání nikoli pouze jedné hodnoty mezi uzly kolony, ale většího množství hodnot. Příkladem může být pokus o transpřeklad a spuštění kolony, do které se předá dvojice hodnot, ta se v prvním uzlu swap otočí a předá se v opačném pořadí do uzlu sub, v němž se hodnoty odečtou. Výsledek je posléze vytisknut funkcí print. Pokud nebudeme mít k dispozici operátor pro předání většího množství hodnot, ale pouze jediné hodnoty, kolona nebude pracovat podle předpokladů:

def swap(x, y):
    return y, x
 
 
def sub(x, y):
    return x - y
 
 
(1, 2) |> swap |> sub |> print

Při pokusu o spuštění se zobrazí chyba:

$ coconut -r pipeline-multiple-arguments-incorrect.coco
 
Compiling         pipeline-multiple-arguments-incorrect.coco ...
CoconutWarning: Populating initial parsing cache (compilation may take longer than usual)...
Compiled to       pipeline-multiple-arguments-incorrect.py .
Traceback (most recent call last):
  File "<frozen runpy>", line 291, in run_path
  File "<frozen runpy>", line 98, in _run_module_code
  File "<frozen runpy>", line 88, in _run_code
  File "/home/ptisnovs/xy/pipeline-multiple-arguments-incorrect.py", line 2910, in
    (print)((sub)((swap)((1, 2))))  #9 (line in Coconut source)
                  ^^^^^^^^^^^^^^
TypeError: swap() missing 1 required positional argument: 'y'

Proč tomu tak je prozradí pohled do traspilovaného kódu:

# Compiled Coconut: -----------------------------------------------------------
 
def swap(x, y):  #1 (line in Coconut source)
    return y, x  #2 (line in Coconut source)
 
 
 
def sub(x, y):  #5 (line in Coconut source)
    return x - y  #6 (line in Coconut source)
 
 
 
(print)((sub)((swap)((1, 2))))  #9 (line in Coconut source)

Po zjednodušení:

# Simplified version of Coconut transpiled into Python
 
def swap(x, y):
    return y, x
 
 
 
def sub(x, y):
    return x - y
 
 
 
print(sub(swap((1, 2))))

11. Kolona umožňující posílání více hodnot současně

Problém příkladu z předchozí kapitoly spočívá v tom, že takto zavolané funkci sub se předá jediný parametr, který bude n-ticí (dvojicí) a nikoli dvojice parametrů. Aby vše fungovalo podle předpokladů, je nutné provést tuto úpravu:

print(sub(*swap(*(1, 2))))
Poznámka: první hvězdička zajistí „rozbalení“ n-tice vrácené z funkce swap, druhá hvězdička pak rozbalení n-tice, která do kolony vstupuje (závorky zde tedy vedly nejenom ke změně priority, ale i významu zápisu kolony).

Aby bylo umožněno si v rámci kolony předávat větší množství hodnot, vznikly operátory |*> a <*|, kde hvězdička, která je součástí jména těchto operátorů, naznačuje rozbalení n-tic do jednotlivých parametrů (což je vlastnost samotného programovacího jazyka Python). Ukažme si příklad použití operátoru |*>, a to společně s uživatelem definovanými funkcemi swap a sub, které akceptují dva parametry a swap navíc vrací dvě návratové hodnoty (resp. n-tici, konkrétně dvojici):

def swap(x, y):
    return y, x
 
 
def sub(x, y):
    return x - y
 
 
(1, 2) |*> print
(1, 2) |*> sub |> print
(1, 2) |*> swap |*> sub |> print

Tento skript by měl být přeložitelný i spustitelný, což si pochopitelně ověříme:

$ coconut -r pipeline-multiple-arguments.coco
 
Compiling         pipeline-multiple-arguments.coco ...
CoconutWarning: Populating initial parsing cache (compilation may take longer than usual)...
Compiled to       pipeline-multiple-arguments.py .
1 2
-1
1

Skript tedy po svém překladu do Pythonu a spuštění vypsal dva parametry předané funkci print, dále výsledek rozdílu parametrů a nakonec výsledek rozdílu parametrů, které však byly nejprve otočeny. Vše je provedeno podle našich předpokladů.

Pro zajímavost se podívejme, tak jako u předchozích příkladů, na výsledek transpilace do Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
def swap(x, y):  #1 (line in Coconut source)
    return y, x  #2 (line in Coconut source)
 
 
 
def sub(x, y):  #5 (line in Coconut source)
    return x - y  #6 (line in Coconut source)
 
 
 
(print)(*(1, 2))  #9 (line in Coconut source)
(print)((sub)(*(1, 2)))  #10 (line in Coconut source)
(print)((sub)(*(swap)(*(1, 2))))  #11 (line in Coconut source)

Zjednodušená podoba téhož transpilovaného zdrojového kódu:

# Simplified version of Coconut transpiled into Python
 
def swap(x, y):
    return y, x
 
 
 
def sub(x, y):
    return x - y
 
 
 
print(*(1, 2))
print(sub(*(1, 2)))
print(sub(*swap(*(1, 2))))
Poznámka: povšimněte si hvězdiček, které zajistí rozbalení n-tic (zde konkrétně dvojic) do jednotlivých parametrů předaných volané funkci swapsub.

12. Standardní či uživatelský operátor v koloně

Ve skutečnosti může být součástí kolony i volání nějakého standardního operátoru (který samozřejmě může být přetížen). To nám umožní, abychom se zbavili nutnosti deklarace funkce sub, protože namísto vložení této funkce do kolony do ní můžeme vložit i standardní operátor. Je zde pouze jediná podmínka – takový operátor musí být zapsán v kulatých závorkách. Předchozí demonstrační příklad je tedy možné přepsat do následující podoby:

def swap(x, y):
    return y, x
 
 
(1, 2) |*> print
(1, 2) |*> (-) |> print
(1, 2) |*> swap |*> (-) |> print

Výsledek transpřekladu ve své originální podobě:

# Compiled Coconut: -----------------------------------------------------------
 
def swap(x, y):  #1 (line in Coconut source)
    return y, x  #2 (line in Coconut source)
 
 
 
(print)(*(1, 2))  #5 (line in Coconut source)
(print)(((_coconut_minus))(*(1, 2)))  #6 (line in Coconut source)
(print)(((_coconut_minus))(*(swap)(*(1, 2))))  #7 (line in Coconut source)

Výsledek transpřekladu po zjednodušení:

# Simplified version of Coconut transpiled into Python
 
def swap(x, y):
    return y, x
 
 
 
print(*(1, 2))
print((_coconut_minus)(*(1, 2)))
print((_coconut_minus)(*swap(*(1, 2))))

Povšimněte si, že se v transpilovaném kódu volá funkce nazvaná _coconut_minus. Ta vypadá následovně:

def _coconut_minus(a, b=_coconut_sentinel):
 """Minus operator (-). Effectively equivalent to (a, b=None) => a - b if b is not None else -a."""
 if b is _coconut_sentinel:
  return -a
 return a - b

jedná se tedy o operátor – (minus) ve své unární i binární podobě.

13. Kolona s funkcemi, do kterých se předávají keyword parametry

Poslední dva operátory určené pro konstrukci kolony se používají tehdy, pokud je nutné do nějaké funkce předávat keyword parametry, tj. parametry, u nichž se zapisuje jak jejich jméno, tak i předávaná hodnota. Příklad volání funkce s keyword parametry:

a, b = swap(x=1, y=2)

V tomto případě může být vstupem do kolony slovník obsahující jména a hodnoty parametrů a díky existenci operátoru |**> (popř. i jeho „převrácené“ podoby) lze takový slovník automaticky transformovat na keyword parametry. Základní chování tohoto operátoru si ověříme na nepatrně upravené funkci swap, viz též úplný zdrojový kód dalšího testovacího skriptu naprogramovaného v jazyce Coconut. Povšimněte si, že v kolonách kombinujeme hned tři typy operátorů, což naznačuje velkou flexibilitu tohoto programovacího jazyka:

def swap(x=0, y=0):
    return y, x
 
 
def sub(x, y):
    return x - y
 
 
params = {
    "x":1,
    "y":2
}
params |**> swap |*> sub |> print
 
params = {
    "y":2,
    "x":1
}
params |**> swap |*> sub |> print

Opět, jako tomu bylo i v předchozích příkladech, si ukážeme výsledek transpřekladu z Coconutu do Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
def swap(x=0, y=0):  #1 (line in Coconut source)
    return y, x  #2 (line in Coconut source)
 
 
 
def sub(x, y):  #5 (line in Coconut source)
    return x - y  #6 (line in Coconut source)
 
 
 
params = _coconut.dict((("x", 1), ("y", 2)))  #9 (line in Coconut source)
(print)((sub)(*(swap)(**params)))  #13 (line in Coconut source)
 
params = _coconut.dict((("y", 2), ("x", 1)))  #15 (line in Coconut source)
(print)((sub)(*(swap)(**params)))  #19 (line in Coconut source)

Po zjednodušení získáme kód, z něhož je jasně patrné, jaké operace se provádí:

# Simplified version of Coconut transpiled into Python
 
def swap(x=0, y=0):
    return y, x
 
 
 
def sub(x, y):
    return x - y
 
 
 
params = _coconut.dict((("x", 1), ("y", 2)))
print(sub(*swap(**params)))
 
params = _coconut.dict((("y", 2), ("x", 1)))
print(sub(*swap(**params)))

14. Kompozice funkcí

Podívejme se na další „funkcionální“ vlastnost programovacího jazyka Coconut. Z běžných funkcí (ale například i z částečně vyhodnocených funkcí) je možné s využitím operátoru .. (tedy dvě tečky) vytvořit kompozici funkcí. To například znamená, že namísto zápisu:

"B" |> ord |> abs |> hex |> print

můžeme použít kompozici tří funkcí:

"B" |> hex..abs..ord |> print

A nejenom to – výslednou kompozici lze přiřadit k symbolu a snadno si tak vlastně vytvořit zcela novou funkci.

Poznámka: ve skutečnosti opět existuje několik variant operátoru .., uvedeny budou v samostatné tabulce.

15. Ukázka kompozice funkcí operátorem ..

Ukažme si kompozici funkcí na třech příkazech, přičemž první dva příkazy budou uvedeny ve dvou variantách – bez kompozice funkcí a s kompozicí:

"B" |> ord |> abs |> hex |> print
 
"B" |> hex..abs..ord |> print
 
range(11) |> reversed |> sum |> print
 
range(11) |> sum..reversed |> print
 
def evens(sequence):
    return filter(x -> x % 2 == 0, sequence)
 
[1, 2, 3, 4, 5, 6, 30] |> sum..evens |> print

Takto bude vypadat výsledek transpřekladu:

# Compiled Coconut: -----------------------------------------------------------
 
(print)((hex)((abs)((ord)("B"))))  #1 (line in Coconut source)
 
(print)((_coconut_forward_compose(ord, abs, hex))("B"))  #3 (line in Coconut source)
 
(print)((sum)((reversed)(range(11))))  #5 (line in Coconut source)
 
(print)((_coconut_forward_compose(reversed, sum))(range(11)))  #7 (line in Coconut source)
 
@_coconut_tco  #9 (line in Coconut source)
def evens(sequence):  #9 (line in Coconut source)
    return _coconut_tail_call(filter, lambda x: x % 2 == 0, sequence)  #10 (line in Coconut source)
 
 
(print)((_coconut_forward_compose(evens, sum))([1, 2, 3, 4, 5, 6, 30]))  #12 (line in Coconut source)

Přičemž funkce _coconut_forward_compose, která je zde volána, vypadá následovně:

def _coconut_forward_compose(func, *funcs):
 """Forward composition operator (..>).
 (..>)(f, g) is effectively equivalent to (*args, **kwargs) => g(f(*args, **kwargs))."""
 return _coconut_base_compose(func, *((f, 0, False) for f in funcs))

16. Uložení výsledku kompozice funkcí do proměnné – konstrukce nové funkce

V případě, že výsledek kompozice uložíme do proměnné (a v tom nám nic nebrání), můžeme tímto postupem zkonstruovat novou funkci. Přitom si povšimněte, že se nikde neuvádí názvy ani počet parametrů, které do nově zkonstruované funkce vstupují; jde tedy o další formu tacit programmingu. Zkusme si předchozí příklad upravit do takové podoby, aby výsledek kompozice skutečně volal jako novou funkci:

foo = hex..abs..ord
 
"B" |> hex..abs..ord |> print
 
"B" |> foo |> print
 
bar = sum..reversed
 
range(11) |> sum..reversed |> print
range(11) |> bar |> print

Zprávy získané po transpřekladu a spuštění tohoto skriptu by měly být totožné s výsledky skriptu předchozího.

17. Další operátory realizující odlišné způsoby kompozice funkcí

Jak jsme si již řekli v předchozím textu, existuje větší množství operátorů sloužících pro vytvoření kompozice funkcí. Tyto operátory se od sebe liší především tím, zda je první funkce v kompozici zavolána jako první nebo jako poslední (matematicky „správně“ je druhá možnost) a taktéž tím, zda se mezi funkcemi přenáší jeden parametr, více parametrů či keyword parametry. A konečně může nově vytvořená funkce detekovat hodnoty None a ukončit v takovém případě svoji činnost, či naopak tuto detekci neprovádět. Celkem je tedy možných 2×3×2=12 kombinací a všechny tyto kombinace jsou programovacím jazykem Coconut podporovány:

bitcoin_skoleni

# Operátor Směr kompozice funkcí Přenos více parametrů Přenos keyword parametrů Detekce None
1 ..> první funkce je zavolána jako první ne ne ne
2 <.. první funkce je zavolána jako poslední ne ne ne
3 ..*> první funkce je zavolána jako první ano ne ne
4 <*.. první funkce je zavolána jako poslední ano ne ne
5 ..**> první funkce je zavolána jako první ne ano ne
6 <**.. první funkce je zavolána jako poslední ne ano ne
7 ..?> první funkce je zavolána jako první ne ne ano
8 <?.. první funkce je zavolána jako poslední ne ne ano
9 ..?*> první funkce je zavolána jako první ano ne ano
10 <*?.. první funkce je zavolána jako poslední ano ne ano
11 ..?**> první funkce je zavolána jako první ano ne ano
12 <**?.. první funkce je zavolána jako poslední ano ne ano

18. Alternativní způsob zápisu operátoru ..

Ve skutečnosti je operátor .. zkráceným zápisem operátoru <... Jeho výsadní postavení spočívá pouze v tom, že se jednalo o první takový operátor, který byl do jazyka Coconut přidán (a proto ho nebylo nutné odlišovat od dalších jedenácti variant). Proto můžeme příklad z patnácté kapitoly přepsat i následujícím způsobem:

foo = hex<..abs<..ord
 
"B" |> hex<..abs<..ord |> print
 
"B" |> foo |> print
 
bar = sum<..reversed
 
range(11) |> sum<..reversed |> print
range(11) |> bar |> print
Poznámka: korektně by se ovšem tento operátor měl zapisovat znakem ∘ (kolečko, resp. jedno z mnoha koleček z Unicode). A skutečně to možné je, připomeňme si tabulku z předchozího článku:
Znak (znaky) Unicode Původní operátor
\u2218 „..“
∘> \u2218> „..>“
<∘ <\u2218 „<..“
∘*> \u2218*> „..*>“
<*∘ <*\u2218 „<*..“
∘**> \u2218**> „..**>“
<**∘ <**\u2218 „<**..“
∘?> \u2218?> „..?>“
<?∘ <?\u2218 „<?..“
∘?*> \u2218?*> „..?*>“
<*?∘ <*?\u2218 „<*?..“
∘?**> \u2218?**> „..?**>“
<**?∘ <**?\u2218 „<**?..“

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
       
76 pipeline-basic.coco základní forma kolony, v níž data proudí zleva doprava https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-basic.coco
77 pipeline-basic.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-basic.py
78 pipeline-backward.coco základní forma kolony, v níž data proudí zprava doleva https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-backward.coco
79 pipeline-backward.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-backward.py
       
80 pipeline-none-not-aware.coco kolona, která nerozeznává hodnoty None https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-none-not-aware.coco
81 pipeline-none-not-aware.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-none-not-aware.py
82 pipeline-none-aware.coco kolona, která rozeznává hodnoty None https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-none-aware.coco
83 pipeline-none-aware.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-none-aware.py
84 pipeline-none-aware-2.coco kolona, která rozeznává hodnoty None, explicitní tisk výsledků https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-none-aware-2.coco
85 pipeline-none-aware-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-none-aware-2.py
       
86 pipeline-backward-none-not-aware.coco „zpětná“ kolona, která nerozeznává hodnoty None https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-backward-none-not-aware.coco
87 pipeline-backward-none-not-aware.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-backward-none-not-aware.py
88 pipeline-backward-none-aware.coco „zpětná“ kolona, která rozeznává hodnoty None https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-backward-none-aware.coco
89 pipeline-backward-none-aware.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-backward-none-aware.py
       
90 pipeline-multiple-arguments.coco kolona přenášející větší množství argumentů mezi funkcemi https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-multiple-arguments.coco
91 pipeline-multiple-arguments.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-multiple-arguments.py
92 pipeline-multiple-arguments-2.coco použití standardního operátoru pro rozdíl v koloně https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-multiple-arguments-2.coco
93 pipeline-multiple-arguments-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-multiple-arguments-2.py
94 pipeline-keyword-arguments.coco kolona přenášející keyword argumenty https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-keyword-arguments.coco
95 pipeline-keyword-arguments.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/pipeline-keyword-arguments.py
       
96 function-composition-1.coco použití kompozice funkcí v koloně https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-1.coco
97 function-composition-1.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-1.py
98 function-composition-2.coco uložení kompozice funkcí do nového symbolu (nové funkce) https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-2.coco
99 function-composition-2.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-2.py
100 function-composition-3.coco kompozice funkcí operátorem <.. https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-3.coco
101 function-composition-3.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-3.py
102 function-composition-4.coco kompozice funkcí a hodnota None https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-4.coco
103 function-composition-4.py výsledek překladu skriptu do standardního Pythonu https://github.com/tisnik/most-popular-python-libs/blob/master/coconut/function-composition-4.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.