Coconut: jazyk naznačující směr budoucího vývoje Pythonu

4. 6. 2024
Doba čtení: 33 minut

Sdílet

Autor: Depositphotos
Už dříve jsme se seznámili se zajímavým funkcionálním jazykem Coconut, který je transpilován do Pythonu. Coconut se ovšem neustále vyvíjí a vyvíjí se i samotný Python, takže nastal čas Coconut oprášit.

Obsah

1. Coconut: jazyk naznačující směr budoucího vývoje Pythonu

2. Paralelní vývoj Pythonu i jazyka Coconut

3. Instalace interpretru a transpileru jazyka Coconut

4. Interaktivní konzole jazyka Coconut

5. Coconut ve funkci transpřekladače

6. Operátory zjednodušující zápis anonymních funkcí

7. Výpočet faktoriálu s využitím anonymních funkcí

8. Využití operátoru |> pro zřetězení operací a vytvoření kolony

9. Ukázky transpřekladu výpočtů faktoriálu z Coconutu do Pythonu

10. Lambda výraz s implicitním parametrem

11. Lambda výraz bez parametru

12. Od lambda výrazu k plnohodnotné anonymní funkci

13. Anonymní funkce s příkazem a výrazem

14. Anonymní funkce s typovými informacemi

15. Curryfikace a částečně vyhodnocené funkce

16. Deklarace částečně vyhodnocených funkcí v Coconutu

17. Příloha A: klávesové zkratky použité v konzoli Coconutu v režimu Emacs

18. Příloha B: klávesové zkratky použité v konzoli Coconutu v režimu Vi

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

20. Odkazy na Internetu

1. Coconut: jazyk naznačující směr budoucího vývoje Pythonu

Už v roce 2017, což je z pohledu vývoje informatiky poměrně dlouhá doba, jsme se na stránkách Roota ve dvojici článků [1] [2] seznámili se zajímavým programovacím jazykem nazvaným Coconut. Připomeňme si, že se jedná o programovací jazyk, který byl původně navržen takovým způsobem, aby byl zpětně kompatibilní s Pythonem, což je důležité, protože Coconut můžeme považovat za sémantické i syntaktické rozšíření samotného Pythonu (program zapsaný v Pythonu je současně i korektním programem psaným v Coconutu; naopak to ovšem pochopitelně neplatí). Z pohledu programátora se Coconut používá jako klasický interpret, ovšem interně provádí transpilaci (či transkompilaci) zapsaného zdrojového kódu (zpět) do Pythonu a tento transpilovaný kód je možné si nechat v případě potřeby zobrazit a zjistit tak, jak jsou jednotlivé jazykové konstrukce Coconutu interně realizovány.

Poznámka: to ovšem znamená, že můžeme využít i všechny AOT a JIT překladače Pythonu i další nástroje typu Mypy, Pyright atd.

V jazyku Coconut jsme již v roce 2017 mohli najít takové jazykové konstrukce (tj. novou syntaxi se zcela novou sémantikou), které podporovaly funkcionální programování a vlastně i prakticky celé funkcionální paradigma, takže v Coconutu pocházejícím z té doby lze najít například funkce vyššího řádu (které ve skutečnosti podporuje i samotný Python, i když někdy poněkud nešikovně), podporu pro neměnitelné (immutable) hodnoty, podporu pro zápis kompozice funkcí či pro tvorbu takzvaných kolon (dnes navíc Coconut podporuje i zápis částečného vyhodnocení funkce). To ovšem nebylo zdaleka vše, protože již ve zmíněném roce 2017 jsme mohli v jazyce Coconut vidět a používat jazykovou konstrukci realizující pattern matching.

Poznámka: na tomto místě se samozřejmě můžeme ptát, jestli má smysl studovat tak minoritní programovací jazyk, jakým Coconut v současnosti bezesporu je. Ovšem Coconut ukazuje a možná do jisté míry i určuje další směřování samotného Pythonu. Příkladem může být podpora pro pattern matching, která se objevila právě v Coconutu a později (konkrétně o přibližně pět let později) byla realizována i v Pythonu, jenž se ovšem inspiroval i v jiných programovacích jazycích, částečně v OCamlu a pravděpodobně i v Rustu.

2. Paralelní vývoj Pythonu i jazyka Coconut

Od vydání obou výše zmíněných článků o programovacím jazyce Coconut již uběhla dlouhá doba, a to především v kontextu s postupným (a poměrně rychlým) vývojem samotného programovacího jazyka Python. Ostatně v roce 2017, kdy se začal Coconut postupně rozšiřovat, byla nejnovější verzí Pythonu (CPythonu) verze 3.6, viz tabulku se všemi verzemi Pythonu 3.x:

Verze Datum vydání
Python 3.0 3. prosince 2008
Python 3.1 27. června 2009
Python 3.2 20. února 2011
Python 3.3 29. září 2012
Python 3.4 16. března 2014
Python 3.5 13. září 2015
Python 3.6 23. prosince 2016
Python 3.7 27. června 2018
Python 3.8 14. října 2019
Python 3.9 5. října 2020
Python 3.10 4. října 2021
Python 3.11 24. října 2022
Python 3.12 2. října 2023

Samotný programovací jazyk Python byl od výše zmíněné verze 3.6 upraven a rozšiřován v mnoha směrech, což je patrné při pohledu na další tabulku, tentokrát s největšími novinkami, které byly ve verzích následujících po verzi 3.6 do tohoto velmi populárního jazyka přidány:

Verze Vybrané nové vlastnosti jazyka
Python 3.7 rezervovaná klíčová slova async a await + jejich sémantika
Python 3.8 mroží operátor (walrus operator), poziční parametry funkcí
Python 3.9 generické datové typy
Python 3.10 pattern matching
Python 3.10 možnost použití operátoru | při definici typů
Python 3.11 skupiny výjimek
Python 3.12 klíčové slovo type + jeho sémantika
Python 3.12 nová syntaxe pro zápis generických typů

Na tyto změny v Pythonu musel projekt Coconut nějakým způsobem reagovat, už jen z toho důvodu, že se v Pythonu 3.10 objevil pattern matching nekompatibilní s původním Coconutem (stručně řečeno – význam klíčových slov match a case byl prohozen). A právě na tyto změny (resp. přesněji řečeno na současný stav Coconutu) se zaměříme v dnešním článku i v článku navazujícím.

3. Instalace interpretru a transpileru jazyka Coconut

Programovací jazyk Coconut, což konkrétně znamená transpiler (transcompiler) upravený do takové podoby, že se chová jako běžný interpret s interaktivní smyčkou REPL (Read-Eval-Print Loop), je možné nainstalovat s využitím běžných správců balíčků ekosystému jazyka Python, tedy například pomocí nástroje pip či pdm. Samotná instalace je zdržena pouze překladem balíčku cPyparsing, který je překládán do nativního kódu (používá se zde technologie Cython, kterou již dobře známe, protože jsme se jí na stránkách Roota již několikrát zabývali).

V případě, že se vám nechce čekat přibližně minutu na dokončení překladu balíčku cPyparsing, lze namísto tohoto balíčku použít pyparsing, jenž je naprogramován v čistém Pythonu a tudíž nevyžaduje překlad. Nevýhodou bude pomalejší běž transpileru Coconutu, což ovšem na našich triviálních demonstračních příkladech vůbec nepocítíme:

$ pip install --user coconut
Collecting coconut
  Downloading coconut-3.1.0-py2.py3-none-any.whl (316 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 316.5/316.5 kB 2.1 MB/s eta 0:00:00
Requirement already satisfied: setuptools>=44 in /usr/lib/python3.11/site-packages (from coconut) (65.5.1)
Collecting cPyparsing<2.4.7.2.4,>=2.4.7.2.3.2
  Downloading cpyparsing-2.4.7.2.3.3.tar.gz (1.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 3.6 MB/s eta 0:00:00
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: psutil>=5 in /home/ptisnovs/.local/lib/python3.11/site-packages (from coconut) (5.9.8)
Requirement already satisfied: prompt-toolkit>=1 in /home/ptisnovs/.local/lib/python3.11/site-packages (from coconut) (3.0.39)
Collecting async-generator>=1.10
  Downloading async_generator-1.10-py3-none-any.whl (18 kB)
Requirement already satisfied: anyio>=3 in /home/ptisnovs/.local/lib/python3.11/site-packages (from coconut) (3.7.1)
Collecting typing-extensions>=4.9
  Downloading typing_extensions-4.12.0-py3-none-any.whl (37 kB)
Collecting pygments>=2.17
  Downloading pygments-2.18.0-py3-none-any.whl (1.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 3.9 MB/s eta 0:00:00
Requirement already satisfied: idna>=2.8 in /usr/lib/python3.11/site-packages (from anyio>=3->coconut) (3.4)
Requirement already satisfied: sniffio>=1.1 in /home/ptisnovs/.local/lib/python3.11/site-packages (from anyio>=3->coconut) (1.3.0)
Requirement already satisfied: wcwidth in /home/ptisnovs/.local/lib/python3.11/site-packages (from prompt-toolkit>=1->coconut) (0.2.8)
Building wheels for collected packages: cPyparsing
  Building wheel for cPyparsing (pyproject.toml) ... done
  Created wheel for cPyparsing: filename=cPyparsing-2.4.7.2.3.3-cp311-cp311-linux_x86_64.whl size=5197614 sha256=8f1c9fabc0e1772db081d487c9eb6122c8a68c7ef0cb47b72312c72fd69e3527
  Stored in directory: /home/ptisnovs/.cache/pip/wheels/ef/31/db/124f8f126b5196bd89cc0b2c4266f27e377efd4a544b90a94a
Successfully built cPyparsing
Installing collected packages: cPyparsing, typing-extensions, pygments, async-generator, coconut
  Attempting uninstall: pygments
    Found existing installation: Pygments 2.16.1
    Uninstalling Pygments-2.16.1:
      Successfully uninstalled Pygments-2.16.1
Successfully installed async-generator-1.10 cPyparsing-2.4.7.2.3.3 coconut-3.1.0 pygments-2.18.0 typing-extensions-4.12.0

Po instalaci by mělo být možné spustit interpret Coconutu s interaktivní smyčkou REPL. Na systému s nainstalovaným Pythonem 3.11 (což je relativně nová verze Pythonu) bude spuštění vypadat následovně:

$ coconut
 
Coconut Interpreter v3.1.0 (Python 3.11):
(enter 'exit()' or press Ctrl-D to end)
>>>

Ve skutečnosti však bude Coconut funkční i v případě, že je v systému nainstalována starší veze Pythonu, například dnes již notně zastaralý Python 3.8:

$ coconut
 
Coconut Interpreter v3.1.0 (Python 3.8):
(enter 'exit()' or press Ctrl-D to end)
Poznámka: podporován je i Python verze 2.x, dnes tedy pravděpodobně 2.7.18, tedy prozatím poslední verze 2.x, kterou ještě můžeme u některých projektů nalézt.

Coconut taktéž podporuje poměrně velké množství přepínačů specifikovaných na příkazové řádce. Tyto přepínače si pochopitelně můžeme vypsat společně s krátkou nápovědou:

$ coconut --help
 
usage: coconut [-h] [--and source [dest ...]] [-v] [-t version] [-i] [-p] [-a] [-l] [--no-line-numbers] [-k] [-w] [-r] [-n] [-d] [-q]
               [-s] [--no-tco] [--no-wrap-types] [-c code] [-j processes] [-f] [--minify] [--jupyter ...] [--mypy ...] [--argv ...]
               [--tutorial] [--docs] [--style name] [--vi-mode] [--recursion-limit limit] [--stack-size kbs] [--fail-fast]
               [--no-cache] [--site-install] [--site-uninstall] [--verbose]
               [source] [dest]
 
docs: http://coconut.readthedocs.io/en/v3.1.0/DOCS.html
 
positional arguments:
  source                path to the Coconut file/folder to compile
  dest                  destination directory for compiled files (defaults to the source directory)
 
options:
  ...
  ...
  ...
Poznámka: pravděpodobně nejpoužívanějším přepínačem je -r, který zajistí transpřeklad následovaný spuštěním vygenerovaného kódu s využitím standardního interpretru Pythonu.

4. Interaktivní konzole jazyka Coconut

Uživatelské rozhraní interaktivní smyčky REPL je v Coconutu oproti klasickému Pythonu (přesněji řečeno CPythonu) vylepšené a do jisté míry připomíná IPython, bpython či PTPython (viz též článek na toto téma). Pravděpodobně nejviditelnějším vylepšením je, že se po stisku klávesy Tab zobrazí kontextové menu se seznamem symbolů, které se k Coconutu vztahují (včetně jeho specifických klíčových slov, funkcí použitelných bez nutnosti importu nějakého balíčku atd.). V interaktivním prostředí Coconutu se navíc barevně zvýrazňují klíčová slova, operátory a některé literály (číselné konstanty a řetězce).

Obrázek 1: Barevné zvýraznění literálů, klíčových slov atd.

Taktéž je možné se vracet a vyhledávat v historii příkazů (Ctrl+R a funkční budou i další známé klávesové zkratky, například pro skoky na začátek a konec řádku (Ctrl+A, Ctrl+E), mazání části zapsaného textu Ctrl+W, Ctrl+K, vložení značky pro výběr (Ctrl+Space) atd. Podporované klávesové zkratky jsou vypsány v příloze A.

Obrázek 2: Vyhledávání v historii zapsaných příkazů.

Poznámka: alternativně lze přepínačem –vimode přepnout režim ovládání interaktivní smyčky takovým způsobem, aby byla do jisté míry kompatibilní s textovými editory Vi/Vim. V takovém případě je interaktivní smyčka přepnuta do režimu vkládání (insert) a pro editaci je nutné stlačit klávesu Esc, stejně jako ve Vi/Vimu. Viz též přílohu B s výpisem některých nejdůležitějších zkratek dostupných v tomto režimu.

Obrázek 3: Kontextové menu s výpisem symbolů obsahujících uživatelem zapsané znaky. Vypisují se pouze symboly vztažené k samotnému Coconutu, nikoli k Pythonu.

5. Coconut ve funkci transpřekladače

Příkaz coconut spustí buď interaktivní smyčku REPL, což jsme si již ostatně ukázali v předchozím textu, nebo ho je možné alternativně použít pro transpřeklad zdrojových kódů z Coconutu do „čistého“ Pythonu. Ukažme si tedy ve stručnosti ještě i tento druhý způsob použití, a to na velmi jednoduchém příkladu, který má na standardní výstup vypsat řetězec „Hello world!“. S využitím nového operátoru pro kolonu (pipeline, ten si popíšeme v dalším textu) je možné takový prográmek napsat například následujícím způsobem:

"Hello, world!" |> print

Překlad, resp. přesněji řečeno transpřeklad, se provede příkazem:

$ coconut hello-world.coco

Průběh transpřekladu:

Compiling         hello-world.coco ...
CoconutWarning: Populating initial parsing cache (compilation may take longer than usual)...
Compiled to       hello-world.py .

Ve výsledném souboru hello-world.py nalezneme výsledek transpřekladu našeho jediného řádku:

# Compiled Coconut: -----------------------------------------------------------
 
(print)("Hello, world!")  #1 (line in Coconut source)

Ve skutečnosti je ovšem soubor hello-world-py mnohem větší; jeho velikost dosahuje přibližně 144 kB. Je tomu tak z toho důvodu, že obsahuje všechny standardní funkce Coconutu (k nim se ještě vrátíme) i pomocné funkce použité v transpilovaném kódu. Přepínačem –minify se můžeme pokusit o zmenšení výsledného souboru, což v tomto případě povede k vygenerování zdrojového souboru Pythonu o velikosti přibližně 126 kB.

Poznámka: nemusíte se však bát, že by velikost souborů, které jsou výsledkem transpřekladu, závratně rostla. Oněch přibližně 140, resp. 120 kB je „startovní hodnota“ a většinou je poměr velikosti kódu v Coconutu ku velikosti odpovídajícího kódu v Pythonu 1:2 nebo i méně.

6. Operátory zjednodušující zápis anonymních funkcí

Velká část změn a vylepšení, které v jazyku Coconut nalezneme, se týká práce s funkcemi, které – jak již název napovídá – tvoří kostru funkcionálního programování. Na některé možnosti Coconutu v této oblasti se nyní zaměříme. Coconut programátorům nabízí i možnost zkráceného zápisu lambda výrazů (což jsou v Pythonu anonymní funkce tvořené jediným výrazem). Následující dva zápisy jsou ekvivalentní, přičemž výraz druhý je kratší a více se podobá „klasické“ lambdě:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"  #1 (line in Coconut source)
words = message.split()
 
filtered = filter(lambda word: len(word) > 4, words)
 
for word in filtered:
    print(word)
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter(word -> len(word) > 4, words)
 
for word in filtered:
    print(word)

Zápis anonymních operací s využitím šipky → je sice stále podporován, ale doporučuje se používat nový styl zápisu s odlišnou šipkou =>. Je tomu tak z toho důvodu, že → se dnes používá i při zápisu typových informací. V dalším textu tedy budeme používat tento zápis anonymní funkce:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter(word => len(word) > 4, words)
 
for word in filtered:
    print(word)

7. Výpočet faktoriálu s využitím anonymních funkcí

Způsob použití nového zápisu anonymních funkcí si ukážeme na výpočtu faktoriálu, což je úloha pro tyto účely téměř ideální. V „čistém“ jazyce Python může být tento výpočet realizován s využitím funkce vyššího řádu reduce, a to následovně:

from functools import reduce
 
 
def factorial(n):
    return reduce(lambda a, b: a*b, range(1, n+1), 1)
 
 
for n in range(0, 11):
    print(n, factorial(n))

Pokusme se tedy o přepis do jazyka Coconut. První varianta by mohla vypadat následovně:

def factorial(n):
    return reduce(a, b => a*b, range(1, n+1), 1)
 
 
for n in range(0, 11):
    print(n, factorial(n))

Problém ovšem spočívá v tom, že se ze syntaktického hlediska nejedná o korektní zápis, protože jazyk nedokáže odvodit, že a není parametrem funkce reduce, ale že patří k definici anonymní funkce. Korektní zápis je nutné provést se závorkami, tedy takto:

def factorial(n):
    return reduce((a, b) => a*b, range(1, n+1), 1)
 
 
for n in range(0, 11):
    print(n, factorial(n))

Tento skript je již možné transpilovat a výsledek spustit běžným způsobem.

Ovšem v Pythonu můžeme i samotnou funkci factorial zapsat přes lambda výraz, což vede k tomu, že v těle jednoho lambda výrazu bude další lambda výraz:

from functools import reduce
 
factorial = lambda n: reduce(lambda a, b: a*b, range(1, n+1), 1)
 
for n in range(0, 11):
    print(n, factorial(n))

Přepis do jazyka Coconut bude v tomto případě snadný, protože již známe podmínku, kterou je nutno splnit (uzávorkování většího množství parametrů):

factorial = n => reduce((a, b) => a*b, range(1, n+1), 1)
 
 
for n in range(0, 11):
    print(n, factorial(n))

A konečně můžeme odstranit i poslední programovou smyčku, protože funkcí vyššího řádu map lze zajistit výpočet celé tabulky faktoriálů. Opět si nejdříve ukažme řešení realizované přímo v Pythonu:

from functools import reduce
 
n = range(0, 11)
 
factorials = map(lambda n: reduce(lambda a, b: a*b, range(1, n+1), 1), n)
 
print(list(factorials))

Přepis do jazyka Coconut s využitím operátoru ⇒ je opět velmi snadný:

n = range(0, 11)
 
factorials = map(n => reduce((a, b) => a*b, range(1, n+1), 1), n)
 
print(list(factorials))

8. Využití operátoru |> pro zřetězení operací a vytvoření kolony

Trošku sice předbíháme, ale ukažme si, jak můžeme nahradit nepěkný zápis s mnoha závorkami (a čtením zprava doleva):

print(list(factorials))

Využijeme zde operátory |>, díky nimž se vytvoří „kolona“ funkcí, které si předávají svoje výstupní hodnoty. Prozatím je vše snadné, protože funkce factorials a list mají jedinou výstupní hodnotu a list a print akceptují jeden vstupní parametr:

n = range(0, 11)
 
factorials = map(n => reduce((a, b) => a*b, range(1, n+1), 1), n)
 
factorials |> list |> print
Poznámka: těchto operátorů pro tvorbu kolony ve skutečnosti existuje celá řada a popsány budou příště.

9. Ukázky transpřekladu výpočtů faktoriálu z Coconutu do Pythonu

Pro zajímavost se ještě podívejme na transpřeklad všech pěti výše uvedených výpočtů faktoriálu z jazyka Coconut do Pythonu. V levém sloupci je uveden zdrojový kód napsaný v Coconutu, ve sloupci pravém pak výsledek tranpřekladu (čistý Python):

def factorial(n):                                                               @_coconut_tco
    return reduce(a, b => a*b, range(1, n+1), 1)                             def factorial(n):
                                                                                    return _coconut_tail_call(reduce, a, lambda b: a * b, range(1, n + 1), 1)

for n in range(0, 11):
    print(n, factorial(n))
                                                                                for n in range(0, 11):
                                                                                    print(n, factorial(n))
def factorial(n):                                                               @_coconut_tco
    return reduce((a, b) => a*b, range(1, n+1), 1)                           def factorial(n):
                                                                                    return _coconut_tail_call(reduce, lambda a, b: a * b, range(1, n + 1), 1)

for n in range(0, 11):
    print(n, factorial(n))
                                                                                for n in range(0, 11):
                                                                                    print(n, factorial(n))
factorial = n => reduce((a, b) => a*b, range(1, n+1), 1)                  factorial = lambda n: reduce(lambda a, b: a * b, range(1, n + 1), 1)


for n in range(0, 11):                                                          for n in range(0, 11):
    print(n, factorial(n))                                                          print(n, factorial(n))
n = range(0, 11)                                                                n = range(0, 11)

factorials = map(n => reduce((a, b) => a*b, range(1, n+1), 1), n)         factorials = map(lambda n: reduce(lambda a, b: a * b, range(1, n + 1), 1), n)

print(list(factorials))                                                         print(list(factorials))
n = range(0, 11)                                                                n = range(0, 11)

factorials = map(n => reduce((a, b) => a*b, range(1, n+1), 1), n)         factorials = map(lambda n: reduce(lambda a, b: a * b, range(1, n + 1), 1), n)

factorials |> list |> print                                                       (print)((list)(factorials))

10. Lambda výraz s implicitním parametrem

V jazyce Coconut je možné v případě, že anonymní funkce (lambda výraz) akceptuje pouze jediný parametr, jméno tohoto parametru před šipkou ⇒ vynechat. V těle takto zapsané anonymní funkce se namísto jména parametru v takovém případě použije pouze podtržítko. To znamená, že zápis mnoha lambda výrazů může být zkrácen, protože mnoho výrazů akceptuje právě jediný parametr. Opět si to ukažme na příkladu filtrace slov ze vstupního řetězce na základě jejich délky:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter(=> len(_) > 4, words)
 
for word in filtered:
    print(word)

Transpřeklad tohoto skriptu do Pythonu bude vypadat následovně:

# Compiled Coconut: -----------------------------------------------------------
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"  #1 (line in Coconut source)
words = message.split()  #2 (line in Coconut source)
 
filtered = filter(lambda _=None: len(_) > 4, words)  #4 (line in Coconut source)
 
for word in filtered:  #6 (line in Coconut source)
    print(word)  #7 (line in Coconut source)

Výsledky běhu skriptu:

Lorem
ipsum
dolor
amet,
consectetur
adipiscing
elit,
eiusmod
tempor
incididunt
labore
dolore
magna
aliqua

11. Lambda výraz bez parametru

Pokud se pozorněji podíváme na způsob transpilace anonymní funkce s jediným parametrem do Pythonu, zjistíme, že se vlastně jedná o lambda výraz s nepovinným parametrem. Z toho vyplývá, že v jazyku Coconut můžeme deklarovat i anonymní funkce bez parametrů. Nejedná se sice v naprosté většině případů o čisté funkce, ale to neznamená, že by se nejednalo o užitečné konstrukce. Můžeme se například pokusit o náhodný výběr zhruba poloviny slov ze zadaného řetězce:

import random
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter(=> random.random() > 0.5, words)
 
for word in filtered:
    print(word)

Způsob transpilace tohoto skriptu do Pythonu:

# Compiled Coconut: -----------------------------------------------------------
 
import random  #1 (line in Coconut source)
 
message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"  #3 (line in Coconut source)
words = message.split()  #4 (line in Coconut source)
 
filtered = filter(lambda _=None: random.random() > 0.5, words)  #6 (line in Coconut source)
 
for word in filtered:  #8 (line in Coconut source)
    print(word)  #9 (line in Coconut source)

Opět si ukažme výsledek běhu tohoto skriptu (pouze příklad – výsledek bude pseudonáhodný):

Lorem
ipsum
dolor
amet,
adipiscing
elit,
sed
do
eiusmod
incididunt
et
dolore
magna
aliqua

12. Od lambda výrazu k plnohodnotné anonymní funkci

Standardní programovací jazyk Python podporuje zápis lambda výrazů, což již ostatně víme. A navíc známe taktéž způsob přepisu do jazyka Coconut. Ovšem lambda výrazy mají jedno velké omezení, které je skryto už v jejich názvu – jejich tělo je totiž skutečně tvořeno jedním výrazem (s určitými triky). Ovšem jak lze zapsat plnohodnotnou anonymní funkci se smyčkou, více výrazy atd.? Ve standardním Pythonu to možné není, ale v jazyku Coconut naopak ano. Pro tento účel se používají takzvané „statement lambdas“, což je nepřesný název pro plnohodnotné anonymní funkce.

Anonymní funkce s potenciálně větším množstvím výrazů přitom nemusí obsahovat příkaz return, protože je vrácena hodnota posledního zapsaného výrazu (musí jít o výraz). Podívejme se na jednoduchý příklad, v němž je anonymní funkce podtržena:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter((def (word) => len(word) > 4), words)
 
for word in filtered:
    print(word)
Poznámka: zápis se tedy podobá například jazyku Go, pokud odhlédneme od použití klíčového slova def a nikoli func. Zde ovšem navíc ponecháváme kulaté závorky okolo anonymní funkce.

Překlad do Pythonu dopadne následovně:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"  #1 (line in Coconut source)
words = message.split()
 
def _coconut_lambda_0(word):
    return len(word) > 4
 
filtered = filter((_coconut_lambda_0), words)
 
for word in filtered:  #6 (line in Coconut source)
    print(word)
Poznámka: z anonymní funkce je tedy vytvořena běžná funkce.

13. Anonymní funkce s příkazem a výrazem

Předchozí demonstrační příklad je možné upravit do takové podoby, ve které se v anonymní funkci skutečně použije nikoli pouze jediný výraz, ale příkaz následovaný výrazem. Onen příkaz slouží k natavení lokální proměnné length; tato proměnná je následně použita ve výrazu, který vypočítá výsledek anonymní funkce:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter((def (word) => length = len(word); length > 4), words)
 
for word in filtered:
    print(word)
Poznámka: zde je již patrné, že taková funkce není příliš čitelná, takže většinou nemá smysl pokoušet se „anonymizovat“ například algoritmus se dvěma vnořenými smyčkami a několika podmínkami.

A takto vypadá transpřeklad původně anonymní funkce do čistého Pythonu:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"  #1 (line in Coconut source)
words = message.split()
 
def _coconut_lambda_0(word):
    length = len(word)
    return length > 4
 
filtered = filter((_coconut_lambda_0), words)
 
for word in filtered:  #6 (line in Coconut source)
    print(word)

14. Anonymní funkce s typovými informacemi

Zápis anonymních funkcí začínajících klíčovým slovem def nám navíc umožňuje specifikaci typových informací, tj. typů parametrů i typu návratové hodnoty (či hodnot). To u běžných lambda výrazů není možné. A navíc si při zápisu typových informací uvědomíme, proč se původní operátor → změnil na => – nedojde k nedorozumění, zda se zapisuje typ návratové hodnoty nebo tělo lambda výrazu či anonymní funkce:

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
filtered = filter((def (word: int) -> int => length = len(word); length > 4), words)
 
for word in filtered:
    print(word)

Takový kód se překládá pro Python 2 bez generování typových informací (použijte parametr –target):

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
def _coconut_lambda_0(word
    ):  #4 (line in Coconut source)
# type: (...) -> int
    length = len(word)
    return length > 4
 
filtered = filter((_coconut_lambda_0), words)
 
for word in filtered:
    print(word)

Naopak pro Python 3 se překlad (transpilace) provede s uvedením všech typových informací (opět použijte přepínač –target):

message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
words = message.split()
 
def _coconut_lambda_0(word: int) -> int:
    length = len(word)
    return length > 4
 
filtered = filter((_coconut_lambda_0), words)
 
for word in filtered:
    print(word)
Poznámka: vzhledem k tomu, že výchozí cílovou verzí Pythonu je Python 2, je nutné při použití typových informací vždy uvést –target, jinak je oznámena chyba.

15. Curryfikace a částečně vyhodnocené funkce

„Typically, developers learn new languages by applying what they know about existing languages. But learning a new paradigm is difficult – you must learn to see different solutions to familiar problems.“

V závěru dnešního článku si ukážeme, jakým způsobem se v programovacím jazyku Python provádí takzvaná curryfikace (anglicky currying). Pod tímto termínem se v teorii programovacích jazyků (ovšem i obecně v matematice) označuje proces, jímž se transformuje funkce, která má více než jeden parametr, do řady vložených funkcí, přičemž každá z nich má jen jediný parametr (jen na okraj – čistou funkci bez parametrů lze nahradit konstantou). Curryfikaci si můžeme představit jako postupnou transformaci funkce s n parametry na jinak zkonstruovanou funkci s n-1 parametry atd. až rekurzivně dojdeme k funkci s jediným parametrem:

x = f(a,b,c) →
    h = g(a)
    i = h(b)
    x = i(c)

Nebo na jediném řádku:

x = f(a,b,c) → g(a)(b)(c)

Částečné vyhodnocení funkce je realizováno například funkcí partial, kterou použijeme v příkladu s funkcí mul, která akceptuje dva parametry. Tyto parametry jsou vynásobeny a výsledek tohoto součinu je současně i návratovou hodnotou funkce mul. S využitím partial se tato funkce se dvěma parametry transformuje na novou funkci pojmenovanou doubler, která ovšem již akceptuje pouze jediný parametr y, neboť původní první parametr x byl nahrazen za dvojku. Následně se již funkce doubler volá s jediným parametrem:

from functools import partial
 
 
def mul(x, y):
    return x * y
 
 
print(mul(6, 7))
 
print()
 
doubler = partial(mul, 2)
 
 
for i in range(11):
    print(i, doubler(i))

16. Deklarace částečně vyhodnocených funkcí v Coconutu

V jazyce Coconut existuje velmi elegantní způsob zápisu konstrukce částečně vyhodnocené funkce. Tento způsob je založen na zápisu znaku $ za jméno jakékoli funkce, které se předají nějaké parametry (typicky méně parametrů, než funkce očekává). Výsledkem bude částečně vyhodnocená funkce, kterou lze zavolat později.

Skript z předchozí kapitoly lze do Coconutu přepsat tímto způsobem:

def mul(x, y):
    return x * y
 
 
print(mul(6, 7))
 
print()
 
doubler = mul$(2)
 
 
for i in range(11):
    print(i, doubler(i))
def mul(x, y):
    return x * y
 
 
 
print(mul(6, 7))
 
print()
 
doubler = _coconut_partial(mul, 2)
 
 
for i in range(11):
    print(i, doubler(i))

Další příklad, tentokrát s funkcí se třemi parametry:

def mul(x, y, z):
    return x * y * z
 
 
print(mul(2, 3, 7))
 
print()
 
doubler = mul$(2)
 
 
for i in range(11):
    print(i, doubler(i, 10))

Popř. pro funkci se čtyřmi parametry – částečné vyhodnocení částečně vyhodnocených funkcí:

def mul(x, y, z, w):
    return x * y * z * w
 
 
f1 = mul
print(f1)
 
f2 = f1$(2)
print(f2)
 
f3 = f2$(3)
print(f3)
 
f4 = f3$(4)
print(f4)
 
f5 = f4$(5)
print(f5)
 
f6 = f5$(6)
print(f6)
 
print()
 
print(f1(2, 3, 4, 5))
print(f2(3, 4, 5))
print(f3(4, 5))
print(f4(5))
print(f5())
print(f6())

17. Příloha A: klávesové zkratky použité v konzoli Coconutu v režimu Emacs

V této příloze jsou vypsány vybrané klávesové zkratky, které jsou ve výchozím nastavení použity v interaktivní konzoli programovacího jazyka Coconut v režimu emulace Emacsu. V tomto režimu není zapotřebí přepínání režimů a většina příkazů je realizována klávesovou kombinací Ctrl+znak nebo Alt+znak. Současně se (pokud si neprovedete rekonfiguraci) jedná o stejné příkazy, jakými se ovládá příkazový řádek samotného shellu nebo standardního Pythonu (resp. přesněji řečeno jeho novějších verzí).

Příkazy pro přesuny kurzoru

Základní příkazy pro přesun kurzoru používají kombinaci Ctrl+znak, Alt+znak, popř. alternativně Esc, znak v případě, že zkratky Alt+znak kolidují s emulátorem terminálu (například vyvolávají příkazy z menu). Pokud je terminál správně nakonfigurován, měly by fungovat i kurzorové šipky a navíc i klávesy Home a End (se zřejmou funkcí):

Klávesa Význam
Ctrl+B přesun kurzoru na předchozí znak
Ctrl+F přesun kurzoru na další znak
   
Alt+B přesun kurzoru na předchozí slovo
Alt+F přesun kurzoru na další slovo
Esc, B shodné s klávesovou zkratkou Alt+B
Esc, F shodné s klávesovou zkratkou Alt+F
   
Ctrl+A přesun kurzoru na začátek řádku
Ctrl+E přesun kurzoru na konec řádku

Mazání textu, práce s kill ringem

Pro přesun části textu v rámci editovaného řádku se používá takzvaný kill ring, do něhož se smazaný text uloží. Pro vložení takto smazaného textu do jiné oblasti se používá operace nazvaná yank (odpovídá paste). Některé dále uvedené příkazy dokážou s kill ringem pracovat:

Klávesa Význam
Ctrl+K smaže text od kurzoru do konce řádku a uloží ho do kill ringu
Ctrl+U smaže text od začátku řádku do pozice kurzoru a uloží ho do kill ringu
Ctrl+W smaže předchozí slovo a uloží ho do kill ringu
Alt+D smaže následující slovo a uloží ho do kill ringu
   
Ctrl+Y vloží text z kill ringu na místo, na němž se nachází kurzor (yank)
Alt+Y po operaci Ctrl+Y dokáže rotovat historií kill ringu a obnovit tak (před)předchozí smazaný text
   
Ctrl+D smaže jeden znak (pokud je ovšem na řádku nějaký obsah, jinak typicky ukončí aplikaci, resp. interaktivní smyčku Coconutu)

Práce s historií dříve zadaných příkazů

Klávesa Význam
Ctrl+P průchod historií – předchozí text
Ctrl+N průchod historií – následující text
Ctrl+R zpětné (interaktivní) vyhledávání v historii
Ctrl+G ukončení režimu vyhledávání zapnutého předchozí zkratkou

Některé další dostupné příkazy

Klávesa Význam
Tab implicitní klávesa pro zavolání completeru jazyka Coconut (kontextové menu)
Ctrl+T prohození dvou znaků (před kurzorem a na pozici kurzoru)
   
Alt+U text od pozice kurzoru do konce slova se změní NA VERZÁLKY
Alt+L text od pozice kurzoru do konce slova se změní na mínusky
Alt+C text od pozice kurzoru do konce slova se změní Tak, Že Slova Začínají Velkým Písmenem

18. Příloha B: klávesové zkratky použité v konzoli Coconutu v režimu Vi

Pokud je Coconut spuštěn s volbou –vimode, bude se příkazová řádka ovládat příkazy napodobující editory Vi/Vim.

Poznámka: ve výchozím nastavení se řádka konzole programovacího jazyka Coconutu nachází v režimu vkládání znaků (insert mode). Pro přepnutí do normálního režimu použijte Esc.

V režimu emulace editorů Vi/Vim je možné mj. použít i tyto klávesové zkratky:

Příkazy pro přesuny kurzoru

Tyto příkazy jsou platné pro normální režim a lze je zkombinovat s operátory (delete, change, yank atd.):

bitcoin školení listopad 24

Klávesa Význam
h přechod na předchozí znak
l přechod na další znak
b skok (zpět) na první znak slova
e skok na poslední znak slova
w skok na první znak následujícího slova
0 skok na začátek řádku
$ skok na konec řádku
% doskok na párovou závorku
f skok na specifikovaný znak (find)

Editace textu

Klávesa Význam
x smazání jednoho znaku (odpovídá klávese Delete)
d operace smazání textu (musí být následována příkazem pro pohyb kurzoru)
D smazání textu od pozice kurzoru do konce řádku
y přenos textu do registru _ (musí být následována příkazem pro pohyb kurzoru)
c změna textu (musí být následována příkazem pro pohyb kurzoru)
r změna jediného znaku
s změna jediného znaku a přechod do vkládacího režimu
p operace put/paste, vloží smazaný text od pozice kurzoru
P operace put/paste, vloží smazaný text před pozicí kurzoru

Příkazy ve vkládacím režimu

Některé příkazy ve vkládacím režimu odpovídají režimu Emacsu (viz předchozí kapitolu):

Klávesa Význam
Ctrl+H smazání znaku nalevo od kurzoru (odpovídá Backspace)
Ctrl+R zpětné (interaktivní) vyhledávání v historii
Ctrl+W smaže předchozí slovo a uloží ho do kill ringu

Další příkazy

Klávesa Význam
Esc přepnutí do normálního režimu
1–9 prefix pro opakování další operace
u vrácení poslední operace (lze opakovat)
a append – přechod do režimu vkládání
i insert – přechod do režimu vkládání
~ změna jednoho znaku: verzálky/kapitálky a zpět
k průchod historií – předchozí text
j průchod historií – následující text

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

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. PEP 634 – Structural Pattern Matching: Specification
    https://peps.python.org/pep-0634/
  8. PEP 635 – Structural Pattern Matching: Motivation and Rationale
    https://peps.python.org/pep-0635/
  9. PEP 636 – Structural Pattern Matching: Tutorial
    https://peps.python.org/pep-0636/
  10. PEP 622 – Structural Pattern Matching
    https://peps.python.org/pep-0622/
  11. Python 3.10 se strukturálním pattern matchingem
    https://www.root.cz/zpravicky/python-3–10-se-strukturalnim-pattern-matchingem/
  12. Null coalescing operator
    https://en.wikipedia.org/wi­ki/Null_coalescing_operator
  13. Operátor koalescence
    https://cs.wikipedia.org/wi­ki/Oper%C3%A1tor_koalescen­ce
  14. Elvis operator
    https://en.wikipedia.org/wi­ki/Elvis_operator
  15. Safe navigation operator
    https://en.wikipedia.org/wi­ki/Safe_navigation_operator
  16. Setting stacksize in a python script
    https://stackoverflow.com/qu­estions/5061582/setting-stacksize-in-a-python-script
  17. 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
  18. Does Python optimize tail recursion?
    https://stackoverflow.com/qu­estions/13591970/does-python-optimize-tail-recursion
  19. Programovací jazyk APL: programování bez smyček
    https://www.root.cz/clanky/pro­gramovaci-jazyk-apl-programovani-bez-smycek/
  20. Programovací jazyk APL – dokončení
    https://www.root.cz/clanky/pro­gramovaci-jazyk-apl-dokonceni/
  21. Tail call
    https://en.wikipedia.org/wi­ki/Tail_call
  22. Tail Call Optimization for Python
    https://github.com/baruchel/tco
  23. Tail Recursion Elimination
    http://neopythonic.blogspot­.cz/2009/04/tail-recursion-elimination.html
  24. Origins of Python's „Functional“ Features
    http://python-history.blogspot.cz/2009/04/origins-of-pythons-functional-features.html
  25. Tail recursion decorator revisited
    http://fiber-space.de/wordpress/2009/04/20/tail-recursion-decorator-revisited/
  26. Koncová rekurze
    https://cs.wikipedia.org/wi­ki/Koncov%C3%A1_rekurze
  27. Recursion (computer science)
    https://en.wikipedia.org/wi­ki/Recursion_%28computer_sci­ence%29
  28. Coconut: Simple, elegant, Pythonic functional programming
    http://coconut-lang.org/
  29. coconut 1.1.0 (Python package index)
    https://pypi.python.org/py­pi/coconut/1.1.0
  30. Coconut Tutorial
    http://coconut.readthedoc­s.io/en/master/HELP.html
  31. Coconut FAQ
    http://coconut.readthedoc­s.io/en/master/FAQ.html
  32. Coconut Documentation
    http://coconut.readthedoc­s.io/en/master/DOCS.html
  33. Python gains functional programming syntax via Coconut
    https://www.infoworld.com/ar­ticle/3088058/python-gains-functional-programming-syntax-via-coconut.html
  34. Repositář projektu pyparsing
    https://github.com/pyparsin­g/pyparsing
  35. Repositář projektu cPyparsing
    https://github.com/evhub/cpyparsing
  36. 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/
  37. Coconut na Redditu
    https://www.reddit.com/r/Pyt­hon/comments/4owzu7/coconut_fun­ctional_programming_in_pyt­hon/
  38. Repositář na GitHubu
    https://github.com/evhub/coconut
  39. patterns
    https://github.com/Suor/patterns
  40. Source-to-source compiler
    https://en.wikipedia.org/wiki/Source-to-source_compiler
  41. The Lua VM, on the Web
    https://kripken.github.io/lu­a.vm.js/lua.vm.js.html
  42. Lua.vm.js REPL
    https://kripken.github.io/lu­a.vm.js/repl.html
  43. lua2js
    https://www.npmjs.com/package/lua2js
  44. Wisp na GitHubu
    https://github.com/Gozala/wisp
  45. Wisp playground
    http://www.jeditoolkit.com/try-wisp/
  46. REPL v prohlížeči
    http://www.jeditoolkit.com/in­teractivate-wisp/
  47. Minification (programming)
    https://en.wikipedia.org/wi­ki/Minification_(programmin­g)
  48. 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
  49. JavaScript is Web Assembly Language and that's OK.
    http://www.hanselman.com/blog/Ja­vaScriptIsWebAssemblyLangu­ageAndThatsOK.aspx
  50. Dart
    https://www.dartlang.org/
  51. CoffeeScript
    http://coffeescript.org/
  52. TypeScript
    http://www.typescriptlang.org/
  53. JavaScript: The Web Assembly Language?
    http://www.informit.com/ar­ticles/article.aspx?p=1856657
  54. asm.js
    http://asmjs.org/
  55. List of languages that compile to JS
    https://github.com/jashke­nas/coffeescript/wiki/List-of-languages-that-compile-to-JS
  56. Permutation
    https://en.wikipedia.org/wi­ki/Permutation
  57. Pattern matching (Wikipedia)
    https://en.wikipedia.org/wi­ki/Pattern_matching
  58. Pattern matching v Rustu
    https://www.root.cz/clanky/rust-funkce-lambda-vyrazy-a-rozhodovaci-konstrukce-match/#k13
  59. SNOBOL
    https://en.wikipedia.org/wiki/SNOBOL
  60. Podpůrný plugin pro Vim
    https://github.com/manicma­niac/coconut.vim
  61. Příkaz (programování)
    https://cs.wikipedia.org/wi­ki/P%C5%99%C3%ADkaz_%28pro­gramov%C3%A1n%C3%AD%29
  62. Threading Macros Guide
    https://clojure.org/guides/thre­ading_macros
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.