Když možnosti functools nedostačují: další knihovny pro funkcionální programování v Pythonu

17. 8. 2023
Doba čtení: 36 minut

Sdílet

 Autor: Depositphotos
Ve čtvrtém článku o podpoře funkcionálního programování v jazyku Python se zaměříme na popis knihovny nazvané funcy, která do Pythonu přináší další užitečné funkcionální techniky, mezi než patří currying funkcí a taktéž kompozice funkcí.

Obsah

1. Když možnosti functools nedostačují: další knihovny pro podporu funkcionálního programování pro Python

2. Atributy transformované funkce vytvořené s využitím dekorátoru

3. Využití dekorátoru @wraps pro automatickou úpravu atributů „obalované“ funkce

4. Dekorátor @wraps a několikanásobná aplikace dekorátorů na „obalovanou“ funkci

5. Když možnosti functools už nedostačují: další knihovny pro podporu funkcionálního programování

6. Knihovna funcy

7. Instalace knihovny funcy

8. Zkrácená deklarace dekorátoru s využitím dekorátoru @decorator

9. Několikanásobná aplikace dekorátorů

10. Přepis dekorátoru pro zjištění doby běhu funkce

11. Curryfikace funkce s využitím curry

12. Příklad curryfikace funkce se dvěma parametry

13. Curryfikace funkce se třemi parametry

14. Rozdíl mezi curryfikací funkce s využitím curryrcurry

15. „autocurryfikace“

16. Kompozice funkcí s využitím funkce vyššího řádu compose

17. Kompozice zleva doprava či zprava doleva?

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

19. Příloha: odkazy na články o programovacím jazyku Clojure

20. Odkazy na Internetu

1. Když možnosti functools nedostačují: další knihovny pro podporu funkcionálního programování pro Python

V předchozí trojici článků [1] [2] [3] jsme se zaměřili na ty funkcionální prvky programovacího jazyka Python, které jsou realizovány ve standardní knihovně nazvané příznačně functools. Ovšem na tomto místě je nutno říci, že tato knihovna je pojata poměrně minimalistickým způsobem a nalezneme v ní pouze některé techniky. Co nám ale vlastně ještě chybí? V první řadě lepší podpora pro tvorbu dekorátorů, podpora pro currying funkcí (když se smíříme s tím, že to nedokáže vlastní interpret Pythonu) a v neposlední řadě i podpora pro kompozici funkcí. Jednou z knihoven, která tyto techniky do Pythonu přináší, je knihovna funcy, s jejímiž naprostými základy se seznámíme dnes.

2. Atributy transformované funkce vytvořené s využitím dekorátoru

V předchozím článku jsme se (kromě dalších věcí) seznámili i se způsobem „obalení“ nějaké funkce dalšími příkazy a popř. i nelokálními proměnnými. Připomeňme si, že tato technologie je umožněna díky tomu, že funkce jsou v Pythonu plnohodnotnými datovými typy a tím pádem je (mj.) možné tvořit i uzávěry (closure). Obalení libovolné funkce kódem uvedeným ve funkci wrapper1 se syntakticky řeší takzvaným dekorátorem, v tomto konkrétním případě dekorátorem @wrapper1:

def wrapper1(function):
    def inner_function():
        print("-" * 40)
        function()
        print("-" * 40)
 
    return inner_function
 
 
@wrapper1
def hello():
    print("Hello!")
 
 
hello()
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators2.py.

Vše bude fungovat zdánlivě bez problémů, ovšem nová funkce, která vznikne aplikací dekorátoru (už se totiž v žádném případě nejedná o původní funkci hello), bude mít některé své atributy nastaveny z pohledu uživatele poněkud matoucím způsobem. Můžeme si to ostatně velmi snadno otestovat:

print("function name:", hello.__name__)

Výsledek bude pro uživatele takové funkce matoucí a navíc i nejednoznačný v případě, kdy použijeme dekorátor wrapper1 vícekrát:

function name: inner_function

3. Využití dekorátoru @wraps pro automatickou úpravu atributů „obalované“ funkce

Problém zmíněný v předchozí kapitole lze velmi snadno vyřešit použitím (dalšího) dekorátoru pojmenovaného @wraps, který nalezneme v balíčku functools. Tento dekorátor se však neaplikuje na uživatelskou funkci, kterou je třeba transformovat, ale na nově vznikající funkci definovanou ve wrapperu a vracenou jako jeho návratovou hodnota. Celá úprava demonstračního příkladu z předchozí kapitoly bude vypadat následovně (dekorátor byl přidán k funkci inner_function):

from functools import wraps
 
 
def wrapper1(function):
    @wraps(function)
    def inner_function():
        print("-" * 40)
        function()
        print("-" * 40)
 
    return inner_function
 
 
@wrapper1
def hello():
    print("Hello!")
 
 
hello()
 
print("function name:", hello.__name__)
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators5.py.

Výsledek bude nyní vypadat následovně:

----------------------------------------
Hello!
----------------------------------------
function name: hello
Poznámka: z oněch zobrazených čtyř řádků je patrné, že původní dekorátor @wrapper je stále plně funkční a navíc je i jméno nové funkce korektní (alespoň z pohledu uživatele takové funkce – který navíc nemusí nic vědět o tom, jak vlastně dekorátory fungují).

4. Dekorátor @wraps a několikanásobná aplikace dekorátorů na „obalovanou“ funkci

Dekorátor @wraps, s nímž jsme se ve stručnosti seznámili v předchozím textu, je „tranzitivní“ ve smyslu, že pomůže zachovat původní jméno (popř. i další atributy) funkce, která je transformována větším množstvím dekorátorů. Opět se podívejme na vhodný demonstrační příklad, který vychází z nám již známého příkladu, kdy funkci hello transformujeme s využitím dekorátorů nazvaných jednoduše @wrapper1 @wrapper2:

from functools import wraps
 
 
def wrapper1(function):
    @wraps(function)
    def inner_function():
        print("-" * 40)
        function()
        print("-" * 40)
 
    return inner_function
 
 
def wrapper2(function):
    @wraps(function)
    def inner_function():
        print("=" * 40)
        function()
        print("=" * 40)
 
    return inner_function
 
 
@wrapper1
@wrapper2
def hello():
    print("Hello!")
 
 
hello()
print("function name:", hello.__name__)
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators6.py.

V případě, že tento skript spustíme, vypíšou se nejdříve zprávy produkované transformovanou funkcí, resp. přesněji řečeno funkcí obalenou dvojicí dekorátorů. A na posledním řádku se korektně vypíše původní jméno funkce, které by jinak bylo ztraceno při transformaci (protože se technicky již jedná o funkci nazvanou inner_function):

----------------------------------------
========================================
Hello!
========================================
----------------------------------------
function name: hello

5. Když možnosti functools už nedostačují: další knihovny pro podporu funkcionálního programování

V této sérii článků jsme si popsali většinu vlastností standardní knihovny functools, která do Pythonu přináší některé prvky funkcionálního programování. Ovšem některé funkcionální vlastnosti tato knihovna nepokrývá či pokrývá jen částečně. Jedná se jak o podporu kompozice funkcí, popř. curryingu (i když partial je částečným (sic) řešením), tak i například o podporu pro neměnitelné datové typy, funkcí pro zpracování sekvencí, podporu typů Option či Result (tak jsou pojmenované v Rustu) atd. Z tohoto důvodu vznikla celá řada více či méně obsáhlých balíčků, z nichž mnohé jsou vyjmenovány (a podle oblíbenosti seřazeny) na stránce Awesome functional Python. V dalším textu se postupně zaměříme především na balíčky Funcy, (Py)Toolz a taktéž Fn.py:

  1. Funcy na GitHubu
    https://github.com/suor/funcy/
  2. PyToolz API Documentation
    https://toolz.readthedocs­.io/en/latest/index.html
  3. Toolz (PyToolz) na GitHubu
    https://github.com/pytoolz/toolz
  4. Fn.py: enjoy FP in Python
    https://github.com/kachayev/fn.py

6. Knihovna funcy

První z knihoven, které do Pythonu přidávají další funkcionální prvky, se jmenuje funcy. Autor této knihovny se nechal inspirovat především vlastnostmi programovacího jazyka Clojure a taktéž vlastnostmi knihovny Underscore (či Lodash) pro ekosystém JavaScriptu. S Clojure jsme se již na stránkách Rootu seznámili v samostatně běžícím seriálu (viz odkazy na konci dnešního článku) a věnovali jsme se i knihovně Underscore, a to konkrétně v článcích Underscore aneb další knihovna pro funkcionální programování v JavaScriptu a Funkce vyššího řádu v knihovně Underscore. Jaké možnosti, vlastnosti a techniky tedy byly z těchto dvou použity v knihovně funcy? Podívejme se na jejich seznam:

  1. Funkce pro zpracování sekvencí (což je abstrakce postavená nad seznamy, n-ticemi atd.)
  2. Funkce pro zpracování kolekcí
  3. Zpracování funkcí – currying, kompozice funkcí a mnoho dalších podobných operací
  4. Podpora pro práci s dekorátory
  5. Podpůrné funkcionální konstrukce pro řízení toku (control flow), typicky založeném na použití dekorátorů a funkcí vyššího řádu
  6. Podpora pro ladění
  7. Podpora pro caching (v poněkud rozšířeném významu oproti nám již známé @lru_cache a @cached_property)
Poznámka: některé vlastnosti se ovšem částečně překrývají s možnostmi jak samotného jazyku Python, tak i jeho standardní knihovny (functools, itertools).

7. Instalace knihovny funcy

Samotná instalace knihovny funcy je velmi snadná, protože tato knihovna neobsahuje žádné překládané části (proto ani její wheel nerozlišuje mezi architekturami) a ani nemá žádné další závislosti:

$ pip3 install --user funcy
 
Collecting funcy
  Downloading funcy-2.0-py2.py3-none-any.whl (30 kB)
Installing collected packages: funcy
Successfully installed funcy-2.0

Nejedná se přitom o nijak obsáhlý balíček, protože jeho zdrojové kódy mají přibližně 2500 řádků:

$ wc -l .local/lib/python3.8/site-packages/funcy/*.py
 
  152 .local/lib/python3.8/site-packages/funcy/calc.py
  362 .local/lib/python3.8/site-packages/funcy/colls.py
   43 .local/lib/python3.8/site-packages/funcy/compat.py
  243 .local/lib/python3.8/site-packages/funcy/debug.py
  184 .local/lib/python3.8/site-packages/funcy/decorators.py
  246 .local/lib/python3.8/site-packages/funcy/flow.py
   28 .local/lib/python3.8/site-packages/funcy/funcmakers.py
   27 .local/lib/python3.8/site-packages/funcy/funcolls.py
  135 .local/lib/python3.8/site-packages/funcy/funcs.py
   21 .local/lib/python3.8/site-packages/funcy/__init__.py
  182 .local/lib/python3.8/site-packages/funcy/_inspect.py
  107 .local/lib/python3.8/site-packages/funcy/objects.py
   28 .local/lib/python3.8/site-packages/funcy/primitives.py
   41 .local/lib/python3.8/site-packages/funcy/py2.py
   32 .local/lib/python3.8/site-packages/funcy/py3.py
  504 .local/lib/python3.8/site-packages/funcy/seqs.py
   78 .local/lib/python3.8/site-packages/funcy/strings.py
   40 .local/lib/python3.8/site-packages/funcy/tree.py
   26 .local/lib/python3.8/site-packages/funcy/types.py
 2479 total

Vyzkoušejme si pro jistotu, zda je možné knihovnu funcy naimportovat a zobrazit si nápovědu k ní:

>>> import funcy
>>> help(funcy)

Po zadání těchto příkazů by se na terminálu měla zobrazit nápověda k naimportovanému balíčku:

Help on package funcy:
 
NAME
    funcy
 
PACKAGE CONTENTS
    _inspect
    calc
    colls
    compat
    debug
    decorators
    flow
    funcmakers
    funcolls
    funcs
    objects
    primitives
    py2
    py3
    seqs
    strings
    tree
    types

8. Zkrácená deklarace dekorátoru s využitím dekorátoru @decorator

Podívejme se nejprve znovu na téma, kterému jsme se věnovali v závěru předchozího článku i na začátku článku dnešního – jak v Pythonu vytvořit dekorátor, tedy vhodně zapsanou funkci, která obalí/transformuje uživatelem zadanou funkci. Víme již, že základní řešení může vypadat následovně:

def wrapper1(function):
    def inner_function():
        print("-" * 40)
        function()
        print("-" * 40)
 
    return inner_function
 
 
@wrapper1
def hello():
    print("Hello!")
 
 
hello()

Toto řešení je čitelné z pohledu uživatele dekorátoru a jeho další výhodou je, že nic neskrývá, protože ze zdrojového kódu funkce wrapper1 je přímo patrné, jaká operace se zde provádí. Na druhou stranu by možná bylo vhodnější si celý zápis zkrátit a zbytečně se nezabývat deklarací wrapperu, prací s interní funkcí, kterou wrapper vrací atd. A právě v takovém případě lze při použití knihovny funcy pro deklaraci dekorátoru použít jiný dekorátor, zde konkrétně dekorátor nazvaný přímočaře @decorator. Jeho použití je až triviálně snadné, protože vlastně namísto původního wrapperu píšeme jen deklaraci „obalovací“ funkce:

from funcy import decorator
 
 
@decorator
def wrapper1(function):
    print("-" * 40)
    function()
    print("-" * 40)
 
 
@wrapper1
def hello():
    print("Hello!")
 
 
hello()
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators1.py.

9. Několikanásobná aplikace dekorátorů

Pro úplnost se ještě podívejme na další již známý příklad. Jedná se o několikanásobnou aplikaci více dekorátorů, což znamená, že původní funkce je transformována do jiné funkce a ta je dále transformována do další funkce (atd.). Připomeňme si, že zdrojový kód tohoto příkladu vypadal takto:

def wrapper1(function):
    def inner_function():
        print("-" * 40)
        function()
        print("-" * 40)
 
    return inner_function
 
 
def wrapper2(function):
    def inner_function():
        print("=" * 40)
        function()
        print("=" * 40)
 
    return inner_function
 
 
@wrapper1
@wrapper2
def hello():
    print("Hello!")
 
 
hello()

Opět se podívejme na způsob zjednodušení celé struktury tohoto příkladu do podoby založené na použití dekorátoru @decorator. Přepis je přímočarý:

from funcy import decorator
 
 
@decorator
def wrapper1(function):
    print("-" * 40)
    function()
    print("-" * 40)
 
 
@decorator
def wrapper2(function):
    print("=" * 40)
    function()
    print("=" * 40)
 
 
@wrapper1
@wrapper2
def hello():
    print("Hello!")
 
 
hello()
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators2.py.

10. Přepis dekorátoru pro zjištění doby běhu funkce

Naposledy se podívejme na použití dekorátoru @decorator z balíčku funcy. Tentokráte upravíme příklad s dekorátorem, který dokáže změnit délku trvání nějaké operace v měřené funkci. Původní zápis vypadal následovně:

# Original code:
# https://pythonbasics.org/decorators/#Real-world-examples
 
 
import time
 
 
def measure_time(func):
    def wrapper(*arg):
        t = time.time()
        res = func(*arg)
        print("Function took " + str(time.time() - t) + " seconds to run")
        return res
 
    return wrapper
 
 
@measure_time
def tested_function(n):
    time.sleep(n)
 
 
tested_function(1)
tested_function(2)

Přepis do stručnější a čitelnější podoby:

from funcy import decorator
import time
 
 
@decorator
def measure_time(func):
    t = time.time()
    res = func()
    print("Function took " + str(time.time() - t) + " seconds to run")
    return res
 
 
@measure_time
def tested_function(n):
    print(f"Sleeping for {n} seconds")
    time.sleep(n)
 
 
tested_function(1)
tested_function(2)
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/me­asure_time.py.

11. Curryfikace funkce s využitím curry

Ve třetí části dnešního článku si ukážeme, jakým způsobem se v programovacím jazyku Python s využitím knihovny funcy 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á akceptuje více než jeden parametr, do řady vložených funkcí, přičemž každá z nich akceptuje jen jediný parametr. 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)
Poznámka: povšimněte si, že funkce g a h musí vracet jiné funkce.

12. Příklad curryfikace funkce se dvěma parametry

Pro otestování možností, které nám nabízí funkce vyššího řádu curry se pokusme o curryfikaci funkce add se dvěma parametry x a y. Výsledkem curryfikace by měla být funkce s jediným parametrem x, která vrací jinou funkci akceptující taktéž jediný parametr (tentokrát y) a teprve po zavolání této funkce se vrátí kýžený výsledek – součet dvou numerických hodnot:

from funcy import curry
 
 
def add(x, y):
    return x + y
 
 
curried = curry(add)
 
print(curried)
print(curried(1))
print(curried(1)(2))  # pozor na umístění závorek!

Podívejme se nyní na vypsané výsledky:

<function curry.<locals>.<lambda> at 0x7efd464f0160>
<function curry.<locals>.<lambda>.<locals>.<lambda> at 0x7efd463350d0>
3

Jak máme tyto výsledky interpretovat?

  1. První řádek popisuje funkci (a my víme, že má jeden parametr)
  2. Druhý řádek vznikl voláním této funkce a výsledkem je jiná funkce (opět akceptující jeden parametr, jak již víme)
  3. A konečně řádek třetí vznikl zavoláním této funkce s kýženým výsledkem 3
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry1.py.

13. Curryfikace funkce se třemi parametry

Ve skutečnosti pochopitelně není curryfikace omezena pouze na funkce se dvěma parametry. Podívejme se tedy na to, jak bude vypadat curryfikace funkce, která akceptuje tři parametry. Pro jednoduchost použijeme funkci, která své tři parametry sečte a vrátí výsledek součtu:

from funcy import curry
 
 
def add3(x, y, z):
    return x + y + z
 
 
curried = curry(add3)
 
print(curried)
print(curried(1))
print(curried(1)(2))     # pozor na umístění závorek!
print(curried(1)(2)(3))  # pozor na umístění závorek!

Po spuštění tohoto skriptu získáme na standardním výstupu následující čtyři řádky:

<function curry.<locals>.<lambda> at 0x7f3ea21d1160>
<function curry.<locals>.<lambda> at 0x7f3ea20160d0>
<function curry.<locals>.<lambda>.<locals>.<lambda> at 0x7f3ea1fa9f70>
6

Postupně se jedná o tyto hodnoty:

  1. Funkce akceptující jeden parametr a vracející novou funkci (která bude opět vracet funkci akceptující jeden parametr).
  2. Funkce akceptující jeden parametr a vracející novou funkci (která již bude vracet konkrétní číselnou hodnotu).
  3. Funkce akceptující jeden parametr, která vrátí výsledek součtu tohoto parametru se svou vnitřní hodnotou 1+2.
  4. Výsledek volání poslední funkce (z předchozího řádku) s parametrem 3.
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry2.py.

14. Rozdíl mezi curryfikací funkce s využitím curryrcurry

Prozatím jsme si curryfikaci ukazovali na dvojici funkcí, jejichž parametry vlastně byly komutativní, protože nezáleželo na jejich pořadí. To sice ve skutečnosti není zcela pravda, protože interní stavy mezifunkcí již na pořadí parametrech závisí, ovšem výsledkem bude pro stejné parametry (bez ohledu na jejich pořadí) stejná hodnota (pochopitelně za předpokladu, že se jedná o celá čísla). Ovšem podívejme se na funkci, kde již na pořadí parametrů záleží. Bude se jednat o funkci pro výpočet podílu hodnot parametrů, takže se zde striktně rozlišuje mezi dělencem a dělitelem:

from funcy import curry
 
 
def div(x, y):
    return x / y
 
 
curried = curry(div)
 
print(curried)
print(curried(1))
print(curried(1)(2))  # pozor na umístění závorek!

Nyní budou výsledky (zejména poslední řádek) vypadat takto:

<function curry.<locals>.<lambda> at 0x7facbefbf160>
<function curry.<locals>.<lambda>.<locals>.<lambda> at 0x7facbee040d0>
0.5

To by nemělo být příliš překvapující, protože výsledkem podílu 1/2 je za určitých předpokladů :-) (správná verze Pythonu) skutečně hodnota 0.5.

Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry1.py.

Ovšem knihovna funcy nabízí programátorům i funkci nazvanou rcurry, která provádí currying od posledního argumentu k argumentu prvnímu, tedy v opačném pořadí. Pro nekomutativní parametry se bude výsledek lišit (a nejen to – zde se dokonce projeví i případná ne-asociativita). Ostatně se podívejme sami, jak se bude lišit výsledek získaný po curryfikaci pomocí rcurry a nikoli pomocí curry:

from funcy import rcurry
 
 
def div(x, y):
    return x / y
 
 
curried = rcurry(div)
 
print(curried)
print(curried(1))
print(curried(1)(2))  # pozor na umístění závorek!

Výsledek bude následující:

<function rcurry.<locals>.<lambda> at 0x7f921d37c160>
<function rcurry.<locals>.<lambda>.<locals>.<lambda> at 0x7f921d1c10d0>
2.0
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry2.py.

Nyní se můžete ptát, k čemu je to vlastně dobré. Ve skutečnosti se může jednat o poměrně užitečnou techniku, jak je to ostatně ukázáno i v dokumentaci. My si ukážeme odlišný příklad, a to generátor funkcí pro výpočet libovolné dopředu zvolené mocniny. Generované funkce tedy budou akceptovat hodnotu x a vrátí xy, kde y je již ve vygenerovaných funkcích pevně „zadrátováno“:

from funcy import rcurry
 
 
def pow(x, y):
    return x ** y
 
 
n_pow = rcurry(pow)
pow2 = n_pow(2)
pow10 = n_pow(10)
 
print(pow2(2))
print(pow10(2))

Funkce pow2 a pow10 byly vygenerovány zavoláním funkce n_pow a předáním mocniny:

4
1024

Z druhého výsledku je zřejmé, že se vrátila hodnota 210.

Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry3.py.

15. „autocurryfikace“

Knihovna funcy jde ovšem ještě dále a kromě „běžných“ funkcí vyššího řádu curry a ncurry nabízí vývojářům ještě jednu curryfikační techniku. Ta je implementována ve funkci vyššího řádu nazvané autocurry. Tato funkce opět akceptuje libovolnou jinou funkci s libovolným počtem parametrů a vrací novou funkci, která se chová jako vzorně curryfikovaná funkce (akceptuje tedy jeden parametr a obecně vrací jinou funkci), ale současně se chová i jako funkce, na kterou jsou aplikovány všechny kombinace partial. Což znamená, že nově vzniklé funkci můžete předat libovolné množství parametrů (až do maxima omezeného původní funkcí) a buď se vrátí curryfikovaná či částečně aplikovaná funkce nebo přímo výsledek.

Zní to složitě? Podívejme se na příklad:

from funcy import autocurry
 
 
def pow(x, y):
    return x ** y
 
 
n_pow = autocurry(pow)
powX = n_pow()
pow2 = n_pow(2)
pow10 = n_pow(10)
pow3to3 = n_pow(3, 3)
 
print(powX(3, 3))
print(pow2(2))
print(pow10(2))
print(pow3to3)

Na řádku:

n_pow = autocurry(pow)

jsme si vyžádali vygenerování nové funkce, která je jak curryfikovanou obdobou vstupní funkce, tak i funkce, která se bude chovat, jako bychom použili partial. To je ostatně patrné na následujících čtyřech řádcích:

powX = n_pow()          # curryfikace/partial bez parametrů (pochopitelně se vrací funkce)
pow2 = n_pow(2)         # curryfikace
pow10 = n_pow(10)       # curryfikace
pow3to3 = n_pow(3, 3)   # partial, ovšem dosazením všech parametrů ihned získáme výsledek (nevrací se funkce)

A výsledky:

27
4
100    # 10^2 nikoli 2^10 !!!
27
Poznámka: Úplný zdrojový kód tohoto demonstračního příkladu naleznete na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/autocurry.py.

16. Kompozice funkcí s využitím funkce vyššího řádu compose

V několika funkcionálních jazycích (a taktéž v jazycích typu FORTH, Factor nebo Joy) je umožněno vytvářet kompozice funkcí, tj. nové funkce, které vzniknou vzájemným voláním funkcí existujících, ovšem s tím, že se při konstrukci kompozice neřeší takové „maličkosti“, jako jsou názvy či počty předávaných parametrů. Ovšem s kompozicí funkcí se setkáme i v dalších jazycích, i když zde se celá technika může nazývat jinak (pipeline) atd.

Podívejme se na velmi jednoduchý příklad, který provede kompozici standardních funkcí len a str, a to konkrétně tak, že se vstupní parametr převede na řetězec funkcí str a následně se vypočte a vrátí délka tohoto řetězce funkcí len. Kompozice je tedy len(str(vstup)):

from funcy import compose
 
 
composed = compose(len, str)
 
print(composed)
print(composed(0))
print(composed(42))
print(composed(1000))

Výsledek by měl vypadat následovně – nejprve se vypíše typ hodnoty composed a následně se vypíšou délky řetězců „0“, „42“ a „1000“:

<function compose.<locals>.<lambda>.<locals>.<lambda> at 0x7f5bf7100160>
1
2
4

Ovšem můžeme použít i funkce s větším množstvím parametrů. Například lze vytvořit kompozici z funkce pro součet dvou hodnot s následným vynásobením mezivýsledku dvojkou:

from funcy import compose
 
 
def add(x, y):
    return x+y
 
 
def double(x):
    return 2*x
 
 
composed = compose(double, add)
 
print(composed(2, 3))
print(composed(-2, -3))

Takto vypadají výsledky:

10
-10

A pro úplnost si ukažme ještě kompozici získanou ze třech funkcí, konkrétně abs(double(add(x,y))):

from funcy import compose
 
 
def add(x, y):
    return x+y
 
 
def double(x):
    return 2*x
 
 
def abs(x):
    if x < 0:
        return -x
    return x
 
 
composed = compose(abs, double, add)
 
print(composed(2, 3))
print(composed(-2, -3))

S výsledkem:

10
10

17. Kompozice zleva doprava či zprava doleva?

Při tvorbě pipeline z funkcí je přirozenější číst kompozici zleva doprava. V tomto případě je výhodnější namísto compose použít funkci vyššího řádu nazvanou rcompose:

from funcy import rcompose
 
 
composed = rcompose(str, len)
 
print(composed)
print(composed(0))
print(composed(42))
print(composed(1000))

Výsledky budou odpovídat příkladu z předchozí kapitoly:

<function compose.<locals>.<lambda>.<locals>.<lambda> at 0x7f9795247160>
1
2
4

Podobně můžeme přepsat i druhý příklad z předchozí kapitoly do této přehlednější podoby:

from funcy import rcompose
 
 
def add(x, y):
    return x+y
 
 
def double(x):
    return 2*x
 
 
composed = rcompose(add, double)
 
print(composed(2, 3))
print(composed(-2, -3))

Výsledky:

10
-10

A poslední příklad byl přepsán do této pipeline:

from funcy import rcompose
 
 
def add(x, y):
    return x+y
 
 
def double(x):
    return 2*x
 
 
def abs(x):
    if x < 0:
        return -x
    return x
 
 
composed = rcompose(add, double, abs)
 
print(composed(2, 3))
print(composed(-2, -3))

Výsledky:

ict ve školství 24

10
10
Poznámka: termín pipeline je v IT skutečně nadužíván a zneužíván, takže se za jeho použití v článku omlouvám :-)

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

Všechny Pythonovské skripty, které jsme si ukázali v úvodním článku, předminule, minule i dnes, naleznete na adrese https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady (pro jejich spuštění je nutné mít nainstalovánu některou z podporovaných verzí Pythonu 3, a pro dnešní příklady i výše zmíněnou knihovnu funcy):

# Příklad Stručný popis Adresa
1 binary_operator.py ukázka funkce vyššího řádu, která jako parametr akceptuje jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/binary_operator.py
2 get_operator1.py ukázka funkce vyššího řádu, která vrací jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator1.py
3 get_operator2.py ukázka funkce vyššího řádu, která vrací jinou funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator2.py
4 standard_operators.py použití standardních operátorů přepsaných do formy funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/standard_operators.py
       
5 binary_operator_types.py varianta příkladu binary_operator.py s plnými typovými deklaracemi https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/binary_operator_types.py
6 get_operator_types.py varianta příkladu get_operator2.py s plnými typovými deklaracemi https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/get_operator_types.py
       
7 map1.py příklad použití funkce map: výpočet délky všech slov v textu https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map1.py
8 map2.py příklad použití funkce map: výpočet absolutní hodnoty všech členů posloupnosti https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map2.py
9 map3.py příklad použití funkce map: aplikace vlastní pojmenované funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map3.py
10 map4.py příklad použití funkce map: aplikace vlastního lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functools/map4.py
       
11 map_list_comprehension1.py přepis skriptu map1.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
12 map_list_comprehension2.py přepis skriptu map2.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
13 map_list_comprehension3.py přepis skriptu map3.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
14 map_list_comprehension4.py přepis skriptu map4.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/map_list_comprehension.py
       
15 filter1.py filtrace dat na základě délky řetězce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter1.py
16 filter2.py filtrace numerických dat podle toho, zda se jedná o sudá či lichá čísla https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter2.py
17 filter3.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter3.py
       
18 filter_list_comprehension1.py přepis skriptu filter_list_comprehension1.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on1.py
19 filter_list_comprehension2.py přepis skriptu filter_list_comprehension2.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on2.py
20 filter_list_comprehension3.py přepis skriptu filter_list_comprehension3.py tak, aby se použila generátorová notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/filter_list_comprehensi­on3.py
       
21 reduce1.py výpočet faktoriálu s využitím funkce vyššího řádu reduce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce1.py
22 reduce2.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce2.py
23 reduce3.py tisk tabulky faktoriálů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce3.py
24 reduce4.py přepis předchozího příkladu s využitím lambda výrazu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce4.py
25 reduce5.py přepis předchozího příkladu s využitím generátorové notace https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/reduce5.py
       
26 return_function.py funkce jako návratová hodnota jiné funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/return_function.py
27 closure_adder1.py příklad použití uzávěru – konstrukce funkce typu adder https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/closure_adder1.py
28 counter_closure1.py nekorektní implementace čítače s využitím uzávěrů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure1.py
29 counter_closure2.py přístup k nelokálnímu symbolu (Python 2.x i Python 3.x) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure2.py
30 counter_closure3.py přístup k nelokálnímu symbolu (pouze Python 3.x) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/counter_closure3.py
       
31 access_nonlocal_symbol.py přístup k nelokálnímu symbolu v uzávěru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/access_nonlocal_symbol.py
32 functions_and_closures.py funkce a uzávěry (umělý příklad) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/functions_and_closures.py
       
33 partial1.py funkce doubler odvozená (redukcí) z univerzálnější funkce mul https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial1.py
34 partial2.py transformace funkce se třemi parametry s využitím partial (nekorektní řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial2.py
35 partial3.py transformace funkce se třemi parametry s využitím partial (korektní řešení) https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial3.py
36 partial4.py transformace funkce s dosazením většího množství parametrů s využitím partial https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial4.py
37 partial5.py několikanásobná transformace původní funkce na několik nových funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial5.py
38 partial6.py postupná transformace již ztransformovaných funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial6.py
39 partial7.py typ originální funkce i funkcí získaných s využitím transformace pomocí partial https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial7.py
40 partial8.py jméno funkce, poziční argumenty funkce a pojmenované argumenty funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial8.py
41 partial9.py transformace reduce a pojmenované argumenty původní funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial9.py
42 partial_A.py získání informací o redukované funkci s pojmenovanými argumenty https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_A.py
       
43 partial_method1.py třída s metodou s parametry https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method1.py
44 partial_method2.py třída s metodou s parametry – vliv volání setteru na stav objektu https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method2.py
45 partial_method3.py metody enable a disable vzniklé transformací set_enabled https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method3.py
46 partial_method4.py další příklad použití funkce partialmethod – doplnění většího množství parametrů při transformaci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/partial_method4.py
       
47 lru_cache1.py klasický výpočet Fibonacciho posloupnosti rekurzivní funkcí https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache1.py
48 lru_cache2.py LRU cache pro výsledky Fibonacciho posloupnosti pro nejčastěji použité vstupy https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache2.py
49 lru_cache3.py přečtení informací o využití LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache3.py
50 lru_cache4.py programové vymazání LRU cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/lru_cache4.py
       
51 cached_property1.py vlastnost bez cache https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property1.py
52 cached_property2.py cache pro vlastnost https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property2.py
53 cached_property3.py cache pro vlastnost https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/cached_property3.py
       
54 total_ordering.py příklad použití total_ordering https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/total_ordering.py
       
55 decorators2.py deklarace a aplikace jednoho dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators2.py
56 decorators3.py deklarace a aplikace více dekorátorů https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators3.py
57 measure_time.py praktické použití dekorátoru – měření doby trvání funkce označené dekorátorem https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/measure_time.py
       
58 decorators4.py atributy transformované funkce vytvořené s využitím dekorátoru https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators4.py
59 decorators5.py využití dekorátoru @wraps pro automatickou úpravu atributů „obalované“ funkce https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators5.py
60 decorators6.py dekorátor @wraps a několikanásobná aplikace dekorátorů na „obalovanou“ funkci https://github.com/tisnik/most-popular-python-libs/blob/master/functool­s/decorators6.py
       
61 decorators1.py zkrácená deklarace dekorátoru s využitím dekorátoru @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators1.py
62 decorators2.py několikanásobná aplikace dekorátorů, dekorátor je vytvořen přes @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/de­corators2.py
63 measure_time.py měření doby trvání funkce označené dekorátorem, dekorátor je vytvořen přes @decorator https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/measure_time.py
       
64 curry1.py curryfikace funkce se dvěma parametry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry1.py
65 curry2.py curryfikace funkce se třemi parametry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/curry2.py
66 rcurry1.py curryfikace funkce div funkcí curry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry1.py
67 rcurry2.py curryfikace funkce div funkcí rcurry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry2.py
68 rcurry3.py curryfikace funkce n_pow funkcí rcurry https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcurry3.py
       
69 autocurry.py curryfikace funkce n_pow funkcí autocurry (s odlišným výsledkem) https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/autocurry.py
       
70 compose1.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose1.py
71 compose2.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose2.py
72 compose3.py kompozice funkcí s využitím funkce vyššího řádu compose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/compose3.py
73 rcompose1.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose1.py
74 rcompose2.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose2.py
75 rcompose3.py kompozice funkcí s využitím funkce vyššího řádu rcompose https://github.com/tisnik/most-popular-python-libs/blob/master/funcy/rcompose3.py

19. Příloha: odkazy na články o programovacím jazyku Clojure

Pro úplnost si uveďme odkazy na články o programovacím jazyku Clojure, jenž byl, podobně jako knihovna Underscore, velkou inspirací pro tvorbu knihovny funcy. Mnoho technik je v Clojure pojmenováno stejně či velmi podobně, jako ve tomu funcy atd.:

  1. Clojure 1: Úvod
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm/
  2. Clojure 2: Symboly, kolekce atd.
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-2-cast/
  3. Clojure 3: Funkcionální programování
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-3-cast-funkcionalni-programovani/
  4. Clojure 4: Kolekce, sekvence a lazy sekvence
    http://www.root.cz/clanky/clojure-aneb-jazyk-umoznujici-tvorbu-bezpecnych-vicevlaknovych-aplikaci-pro-jvm-4-cast-kolekce-sekvence-a-lazy-sekvence/
  5. Clojure 5: Sekvence, lazy sekvence a paralelní programy
    http://www.root.cz/clanky/clojure-a-bezpecne-aplikace-pro-jvm-sekvence-lazy-sekvence-a-paralelni-programy/
  6. Clojure 6: Podpora pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-6-futures-nejsou-jen-financni-derivaty/
  7. Clojure 7: Další funkce pro paralelní programování
    http://www.root.cz/clanky/programovaci-jazyk-clojure-7-dalsi-podpurne-prostredky-pro-paralelni-programovani/
  8. Clojure 8: Identity, stavy, neměnné hodnoty a reference
    http://www.root.cz/clanky/programovaci-jazyk-clojure-8-identity-stavy-nemenne-hodnoty-a-referencni-typy/
  9. Clojure 9: Validátory, pozorovatelé a kooperace s Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-9-validatory-pozorovatele-a-kooperace-mezi-clojure-a-javou/
  10. Clojure 10: Kooperace mezi Clojure a Javou
    http://www.root.cz/clanky/programovaci-jazyk-clojure-10-kooperace-mezi-clojure-a-javou-pokracovani/
  11. Clojure 11: Generátorová notace seznamu/list comprehension
    http://www.root.cz/clanky/programovaci-jazyk-clojure-11-generatorova-notace-seznamu-list-comprehension/
  12. Clojure 12: Překlad programů z Clojure do bajtkódu JVM I:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-12-preklad-programu-z-clojure-do-bajtkodu-jvm/
  13. Clojure 13: Překlad programů z Clojure do bajtkódu JVM II:
    http://www.root.cz/clanky/programovaci-jazyk-clojure-13-preklad-programu-z-clojure-do-bajtkodu-jvm-pokracovani/
  14. Clojure 14: Základy práce se systémem maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-14-zaklady-prace-se-systemem-maker/
  15. Clojure 15: Tvorba uživatelských maker
    http://www.root.cz/clanky/programovaci-jazyk-clojure-15-tvorba-uzivatelskych-maker/
  16. Programovací jazyk Clojure – triky při práci s řetězci
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-retezci/
  17. Programovací jazyk Clojure – triky při práci s kolekcemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-triky-pri-praci-s-kolekcemi/
  18. Programovací jazyk Clojure – práce s mapami a množinami
    http://www.root.cz/clanky/programovaci-jazyk-clojure-prace-s-mapami-a-mnozinami/
  19. Programovací jazyk Clojure – základy zpracování XML
    http://www.root.cz/clanky/programovaci-jazyk-clojure-zaklady-zpracovani-xml/
  20. Programovací jazyk Clojure – testování s využitím knihovny Expectations
    http://www.root.cz/clanky/programovaci-jazyk-clojure-testovani-s-vyuzitim-knihovny-expectations/
  21. Programovací jazyk Clojure – některé užitečné triky použitelné (nejenom) v testech
    http://www.root.cz/clanky/programovaci-jazyk-clojure-nektere-uzitecne-triky-pouzitelne-nejenom-v-testech/
  22. Enlive – výkonný šablonovací systém pro jazyk Clojure
    http://www.root.cz/clanky/enlive-vykonny-sablonovaci-system-pro-jazyk-clojure/
  23. Nástroj Leiningen a programovací jazyk Clojure: tvorba vlastních knihoven pro veřejný repositář Clojars
    http://www.root.cz/clanky/nastroj-leiningen-a-programovaci-jazyk-clojure-tvorba-vlastnich-knihoven-pro-verejny-repositar-clojars/
  24. Novinky v Clojure verze 1.8.0
    http://www.root.cz/clanky/novinky-v-clojure-verze-1–8–0/
  25. Asynchronní programování v Clojure s využitím knihovny core.async
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async/
  26. Asynchronní programování v Clojure s využitím knihovny core.async (pokračování)
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-pokracovani/
  27. Asynchronní programování v Clojure s využitím knihovny core.async (dokončení)
    http://www.root.cz/clanky/asynchronni-programovani-v-clojure-s-vyuzitim-knihovny-core-async-dokonceni/
  28. Vytváříme IRC bota v programovacím jazyce Clojure
    http://www.root.cz/clanky/vytvarime-irc-bota-v-programovacim-jazyce-clojure/
  29. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  30. Multimetody v Clojure aneb polymorfismus bez použití OOP
    https://www.root.cz/clanky/multimetody-v-clojure-aneb-polymorfismus-bez-pouziti-oop/
  31. Práce s externími Java archivy v programovacím jazyku Clojure
    https://www.root.cz/clanky/prace-s-externimi-java-archivy-v-programovacim-jazyku-clojure/
  32. Clojure 16: Složitější uživatelská makra
    http://www.root.cz/clanky/programovaci-jazyk-clojure-16-slozitejsi-uzivatelska-makra/
  33. Clojure 17: Využití standardních maker v praxi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-17-vyuziti-standardnich-maker-v-praxi/
  34. Clojure 18: Základní techniky optimalizace aplikací
    http://www.root.cz/clanky/programovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  35. Clojure 19: Vývojová prostředí pro Clojure
    http://www.root.cz/clanky/programovaci-jazyk-clojure-19-vyvojova-prostredi-pro-clojure/
  36. Clojure 20: Vývojová prostředí pro Clojure (Vim s REPL)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-20-vyvojova-prostredi-pro-clojure-integrace-vimu-s-repl/
  37. Clojure 21: ClojureScript aneb překlad Clojure do JS
    http://www.root.cz/clanky/programovaci-jazyk-clojure-21-clojurescript-aneb-preklad-clojure-do-javascriptu/
  38. Leiningen: nástroj pro správu projektů napsaných v Clojure
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure/
  39. Leiningen: nástroj pro správu projektů napsaných v Clojure (2)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-2/
  40. Leiningen: nástroj pro správu projektů napsaných v Clojure (3)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-3/
  41. Leiningen: nástroj pro správu projektů napsaných v Clojure (4)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-4/
  42. Leiningen: nástroj pro správu projektů napsaných v Clojure (5)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-5/
  43. Leiningen: nástroj pro správu projektů napsaných v Clojure (6)
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-6/
  44. Programovací jazyk Clojure a databáze (1.část)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-databaze-1-cast/
  45. Pluginy pro Leiningen
    http://www.root.cz/clanky/leiningen-nastroj-pro-spravu-projektu-napsanych-v-clojure-pluginy-pro-leiningen/
  46. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi/
  47. Programovací jazyk Clojure a knihovny pro práci s vektory a maticemi (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-knihovny-pro-praci-s-vektory-a-maticemi-2/
  48. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk/
  49. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-2/
  50. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure/
  51. Seesaw: knihovna pro snadnou tvorbu GUI v azyce Clojure (2)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-2/
  52. Seesaw: knihovna pro snadnou tvorbu GUI v jazyce Clojure (3)
    http://www.root.cz/clanky/seesaw-knihovna-pro-snadnou-tvorbu-gui-v-jazyce-clojure-3/
  53. Programovací jazyk Clojure a práce s Gitem
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem/
  54. Programovací jazyk Clojure a práce s Gitem (2)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-a-prace-s-gitem-2/
  55. Programovací jazyk Clojure: syntéza procedurálních textur s využitím knihovny Clisk (dokončení)
    http://www.root.cz/clanky/programovaci-jazyk-clojure-synteza-proceduralnich-textur-s-vyuzitim-knihovny-clisk-dokonceni/
  56. Pixie: lehký skriptovací jazyk s „kouzelnými“ schopnostmi
    https://www.root.cz/clanky/pixie-lehky-skriptovaci-jazyk-s-kouzelnymi-schopnostmi/
  57. Programovací jazyk Pixie: funkce ze základní knihovny a použití FFI
    https://www.root.cz/clanky/pro­gramovaci-jazyk-pixie-funkce-ze-zakladni-knihovny-a-pouziti-ffi/
  58. Novinky v Clojure verze 1.9.0
    https://www.root.cz/clanky/novinky-v-clojure-verze-1–9–0/
  59. Validace dat s využitím knihovny spec v Clojure 1.9.0
    https://www.root.cz/clanky/validace-dat-s-vyuzitim-knihovny-spec-v-clojure-1–9–0/
  60. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure/
  61. Použití jazyka Gherkin při tvorbě testovacích scénářů pro aplikace psané v Clojure (2)
    https://www.root.cz/clanky/pouziti-jazyka-gherkin-pri-tvorbe-testovacich-scenaru-pro-aplikace-psane-v-nbsp-clojure-2/
  62. Incanter: prostředí pro statistické výpočty s grafickým výstupem založené na Clojure
    https://www.root.cz/clanky/incanter-prostredi-pro-statisticke-vypocty-s-grafickym-vystupem-zalozene-na-clojure/
  63. Incanter: operace s maticemi
    https://www.root.cz/clanky/incanter-operace-s-maticemi/
  64. Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
    https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/
  65. Babashka: interpret Clojure určený pro rychlé spouštění utilit z příkazového řádku
    https://www.root.cz/clanky/babashka-interpret-clojure-urceny-pro-rychle-spousteni-utilit-z-prikazoveho-radku/
  66. Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw
    https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw/
  67. Pokročilý streaming založený na Apache Kafce, jazyku Clojure a knihovně Jackdaw (2. část)
    https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-apache-kafce-jazyku-clojure-a-knihovne-jackdaw-2-cast/
  68. Pokročilý streaming založený na projektu Apache Kafka, jazyku Clojure a knihovně Jackdaw (streamy a kolony)
    https://www.root.cz/clanky/pokrocily-streaming-zalozeny-na-projektu-apache-kafka-jazyku-clojure-a-knihovne-jackdaw-streamy-a-kolony/
  69. Řídicí struktury využitelné v programovacím jazyku Clojure
    https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure/
  70. Řídicí struktury využitelné v programovacím jazyku Clojure (dokončení)
    https://www.root.cz/clanky/ridici-struktury-vyuzitelne-v-programovacim-jazyku-clojure-dokonceni/
  71. Formát EDN: extensible data notation
    https://www.root.cz/clanky/format-edn-extensible-data-notation/
  72. Formát EDN: extensible data notation (dokončení)
    https://www.root.cz/clanky/format-edn-extensible-data-notation-dokonceni/
  73. Čtyři různé podoby datové struktury map v programovacím jazyku Clojure
    https://www.root.cz/clanky/ctyri-ruzne-podoby-datove-struktury-map-v-programovacim-jazyku-clojure/
  74. Programová tvorba diagramů v jazyku Clojure s využitím knihovny Rhizome
    https://www.root.cz/clanky/programova-tvorba-diagramu-v-jazyku-clojure-s-vyuzitim-knihovny-rhizome/
  75. Využití Redisu z jazyka Clojure pomocí knihovny Carmine
    https://www.root.cz/clanky/vyuziti-redisu-z-jazyka-clojure-pomoci-knihovny-carmine/
  76. Využití Redisu z jazyka Clojure pomocí knihovny Carmine (dokončení)
    https://www.root.cz/clanky/vyuziti-redisu-z-jazyka-clojure-pomoci-knihovny-carmine-dokonceni/

20. Odkazy na Internetu

  1. functools — Higher-order functions and operations on callable objects
    https://docs.python.org/3/li­brary/functools.html
  2. Functional Programming HOWTO
    https://docs.python.org/3/how­to/functional.html
  3. Functional Programming in Python: When and How to Use It
    https://realpython.com/python-functional-programming/
  4. Functional Programming With Python
    https://realpython.com/learning-paths/functional-programming/
  5. Awesome Functional Python
    https://github.com/sfermigier/awesome-functional-python
  6. Currying
    https://en.wikipedia.org/wi­ki/Currying
  7. Currying in Python – A Beginner’s Introduction
    https://www.askpython.com/pyt­hon/examples/currying-in-python
  8. Fundamental Concepts in Programming Languages
    https://en.wikipedia.org/wi­ki/Fundamental_Concepts_in_Pro­gramming_Languages
  9. When should I use function currying?
    https://stackoverflow.com/qu­estions/24881604/when-should-i-use-function-currying
  10. Toolz
    https://github.com/pytool­z/toolz/tree/master
  11. Coconut: funkcionální jazyk s pattern matchingem kompatibilní s Pythonem
    https://www.root.cz/clanky/coconut-funkcionalni-jazyk-s-pattern-matchingem-kompatibilni-s-pythonem/
  12. A HITCHHIKER'S GUIDE TO functools
    https://ep2021.europython­.eu/media/conference/slides/a-hitchhikers-guide-to-functools.pdf
  13. Coconut aneb funkcionální nadstavba nad Pythonem (2.část)
    https://www.root.cz/clanky/coconut-aneb-funkcionalni-nadstavba-nad-pythonem-2-cast/
  14. Knihovny pro zpracování posloupností (sekvencí) v Pythonu
    https://www.root.cz/clanky/knihovny-pro-zpracovani-posloupnosti-sekvenci-v-pythonu/
  15. clj – repositář s knihovnou
    https://github.com/bfontaine/clj
  16. clj 0.1.0 – stránka na PyPi
    https://pypi.python.org/py­pi/clj/0.1.0
  17. Coconut: Simple, elegant, Pythonic functional programming
    http://coconut-lang.org/
  18. coconut (Python package index)
    https://pypi.python.org/pypi/coconut/
  19. Coconut Tutorial
    http://coconut.readthedoc­s.io/en/master/HELP.html
  20. Coconut FAQ
    http://coconut.readthedoc­s.io/en/master/FAQ.html
  21. Coconut Documentation
    http://coconut.readthedoc­s.io/en/master/DOCS.html
  22. Coconut na Redditu
    https://www.reddit.com/r/Pyt­hon/comments/4owzu7/coconut_fun­ctional_programming_in_pyt­hon/
  23. Repositář na GitHubu
    https://github.com/evhub/coconut
  24. Object-Oriented Programming — The Trillion Dollar Disaster
    https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7
  25. Goodbye, Object Oriented Programming
    https://cscalfani.medium.com/goodbye-object-oriented-programming-a59cda4c0e53
  26. So You Want to be a Functional Programmer (Part 1)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-1–1f15e387e536
  27. So You Want to be a Functional Programmer (Part 2)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-2–7005682cec4a
  28. So You Want to be a Functional Programmer (Part 3)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-3–1b0fd14eb1a7
  29. So You Want to be a Functional Programmer (Part 4)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-4–18fbe3ea9e49
  30. So You Want to be a Functional Programmer (Part 5)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-5-c70adc9cf56a
  31. So You Want to be a Functional Programmer (Part 6)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-6-db502830403
  32. Why Programmers Need Limits
    https://cscalfani.medium.com/why-programmers-need-limits-3d96e1a0a6db
  33. Infographic showing code complexity vs developer experience
    https://twitter.com/rossi­pedia/status/1580639227313676288
  34. Python's reduce(): From Functional to Pythonic Style
    https://realpython.com/python-reduce-function/
  35. What is the problem with reduce()?
    https://stackoverflow.com/qu­estions/181543/what-is-the-problem-with-reduce
  36. The fate of reduce() in Python 3000
    https://www.artima.com/we­blogs/viewpost.jsp?thread=98196
  37. Reading 16: Map, Filter, Reduce
    http://web.mit.edu/6.031/www/sp22/clas­ses/16-map-filter-reduce/
  38. Currying
    https://sw-samuraj.cz/2011/02/currying/
  39. Používání funkcí v F#
    https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions
  40. Funkce vyššího řádu
    http://naucte-se.haskell.cz/funkce-vyssiho-radu
  41. Currying (Wikipedia)
    https://en.wikipedia.org/wi­ki/Currying
  42. Currying (Haskell wiki)
    https://wiki.haskell.org/Currying
  43. Haskell Curry
    https://en.wikipedia.org/wi­ki/Haskell_Curry
  44. Moses Schönfinkel
    https://en.wikipedia.org/wi­ki/Moses_Sch%C3%B6nfinkel
  45. ML – funkcionální jazyk s revolučním typovým systémem
    https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/
  46. Funkce a typový systém programovacího jazyka ML
    https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/
  47. Curryfikace (currying), výjimky a vlastní operátory v jazyku ML
    https://www.root.cz/clanky/curryfikace-currying-vyjimky-a-vlastni-operatory-v-jazyku-ml/
  48. Primer on Python Decorators
    https://realpython.com/primer-on-python-decorators/
  49. Python Decorators
    https://www.programiz.com/python-programming/decorator
  50. PythonDecorators (Python Wiki)
    https://wiki.python.org/mo­in/PythonDecorators
  51. Funcy na GitHubu
    https://github.com/suor/funcy/
  52. Welcome to funcy documentation!
    https://funcy.readthedocs­.io/en/stable/
  53. Funcy cheatsheet
    https://funcy.readthedocs­.io/en/stable/cheatsheet.html
  54. PyToolz API Documentation
    https://toolz.readthedocs­.io/en/latest/index.html
  55. Toolz (PyToolz) na GitHubu
    https://github.com/pytoolz/toolz
  56. Fn.py: enjoy FP in Python
    https://github.com/kachayev/fn.py
  57. Funcy na PyPi
    https://pypi.org/project/funcy/
  58. Underscore aneb další knihovna pro funkcionální programování v JavaScriptu
    https://www.root.cz/clanky/underscore-aneb-dalsi-knihovna-pro-funkcionalni-programovani-v-javascriptu/
  59. Funkce vyššího řádu v knihovně Underscore
    https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/
  60. Awesome functional Python
    https://github.com/sfermigier/awesome-functional-python

Autor článku

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