přihlásit se
k47.cz
Už deset let na vašich monitorech.

Scala - Booleovská kompozice funkcí

autor: kaja47 - CC by-sa - publikováno: - sekce obsah » programování #2371
štítky: , a

projektu Chanminer jsem měl nějaké funkce f, g, h typu A => Boolean a potřeboval jsem je skládat jako kdyby šlo o Boolean hodnoty, např: f && (g || h). Bylo by pěkné, kdyby to šlo takhle přímo, ale bohužel FunctionN nemá žádnou z metod &&, !!, unary_! nebo ^.

Klasické řešení je vytvořit větší funkci, v níž zavolám f, g a h a zkombinuji jejich výsledky:

val x = { (a: A, b: B, c: C) => f(a, b, c) && (g(a, b, c) || h(a, b, c)) }

I když je to funkční řešení, je hned vidět jaké má nevýhody: musím několikrát opakovat všechny argumenty, což člověka začne štvát velice rychle. V ukázce jsou jména argumentů jenom jednopísmenné, kdyby měly popisný název, tak by se v záplavě písmen úplně ztratil záměr kódu.


Pomoci může ScalaZ a monoidy, které se dají k podobnému účelu použít. Monoid je struktura s jednou asociativní binární operací, nulovým prvkem a několika axiomy. Monoid je například definován pro celá čísla, kde operace je + a nulový prvek je 0. Stejně tak je definován i pro funkce A => Boolean, kde operace je logické nebo a nulový prvek je false (zjednodušeně řečeno).

Takže když bych chtěl mezi sebou zorovat několik funkcí, můžu napsat:

val x = f |+| g |+| h

Jak vidno, není to příliš flexibilní řešení.

Stejně jako je na celých číslech definován další monoid, kde operace je násobení a nulový prvek je 1 existuje i na bool funkcích ještě jeden monoid pro and a true, ale aby se použil tenhle musely by naše predikáty vracet speciální typ BooleanConjunction a i tak není možné jednoduše míchat tyhle dva monoidy. Takže nic, tohle mi práci neulehčí.


ScalaZ ale nabízí další užitečnou věc: aplikativní buildery. Pomocí nich můžu naakumulovat několik hodnot/funkcí a na ně potom aplikovat funkci, která bere tolik parametrů, kolik je naakumulováno hodnot (zjednodušeně řečeno):

val x = (f |@| g |@| h) apply (_ && _ && _)

Problém je ale s aplikovanou složitějších funkcí. Když se v nich vyskytne závorka, Scala odvodí funkci s jiným počtem parametrů, než jsem zamýšlel, takže tohle nefunguje:

val x = (f |@| g |@| h) apply ((_ || _) && _) // compiletime error

Jde to takhle:

val x = (f |@| g |@| h) apply (_.||(_) && _)

Ale to si s sebou nese nepříjemně vysoký wtf faktor.

Tenhle nedostatek se dá vyřešit vypuštěním podtržítek z anonymní funkce a pojmenováním všech parametrů:

val x = (f |@| g |@| h) apply { (a, b, c) => (a || b) && c)

Výsledek funguje, ale je poněkud roztahaný.


Žádné z předchozích tří řešeních není ideální. Naštěstí si díky zázraku implicitní konverze můžu napsat několik jednoduchých kombinátorů, se kterými výsledný kód vypadá přesně jak jsem si představoval:


komentáře RSS

Zatím žádné komentáře. Buďte první.
Komentář bude formátován pomocí Texy! syntaxe.
Např: **tučný text**, *kurzíva*, "text odkazu":adresa.
Na ostatní komentáře můžete odkazovat pomocí [čísla komentáře].

Napište komentář!

 

o autorovi:

K. Jmenuji se Karel Čížex, v síti také známý jako kaja47 - tak trochu spisovatel, trochu programátor, trochu webař, milovník divné hudby atd atd.
mail:
jabber: kaja47@jabbim.cz

další projekty

wyhledawacz fel.log stalkr vtipy.k47.cz k47.shop Zkracovač adres stripbot

živě z twitteru

N/A

tadá

poslední články

Slepota v osmadvaceti
článek | 15. května 2016
Star Wars?
film | 9. dubna 2016
Pomalá televize
článek | 24. března 2016
Co se týče komixu...
článek | 29. února 2016
JLB:TUOT
| 6. února 2016
Chris Morris
článek | 21. ledna 2016
Terminalita #35 - Detektiv Toborin
povídka | 31. prosince 2015
Terminalita #34 - Malej Marty
povídka | 31. prosince 2015

poslední komentáře

Pixel dump
cialis_india | 21. května 2016
Slepota v osmadvaceti
Woodbin | 15. května 2016
MySQL: rychlý výběr náhodného záznamu
Tomas Hanke | 22. března 2016
Kosinová podobnost
Mat | 9. prosince 2015
NaNoWriNo, sedmý den, rychlá aktualizace
Pravidelný čtenář odjinud | 18. listopadu 2015
Jak jsem se (skoro) stal vegetariánem
kaja47 | 16. července 2015
Jak jsem se (skoro) stal vegetariánem
Michy | 16. července 2015
Ray Bradbury - 451 stupňů Fahrenheita
Anonym | 10. července 2015

největší kecalové

Mat Mat
Pravidelný čtenář odjinud Pravidelný čtenář odjinud
Michy Michy
Anonym Anonym
Woodbin Woodbin

K47i © 2002 - 2016 K. aka Kaja47