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

Slova starého feťáka
článek | 17. dubna 2014
669.350
| 8. dubna 2014
Sny cypherpunků
článek | 17. března 2014
Přinesla si na to dokonce vlastní provaz
článek | 20. února 2014
Plánované zastarání
článek | 27. ledna 2014
Strach a hnus v Silicon Valley
článek | 25. ledna 2014
10 let a nějaké ty statistiky
interní článek | 31. prosince 2013
Město se kterým není něco v pořádku
článek | 13. listopadu 2013
Sedm let post-rocku
hudební článek | 7. listopadu 2013

poslední komentáře

MySQL group by trik
mrsa | 20. března 2014
Vodník
cbvcxy | 22. února 2014
Rozdělení velkých tříd ve Scale
JeLiTo | 11. ledna 2014
Božena Němcová - V zámku a podzámčí
Anonym | 27. prosince 2013
Sedm let post-rocku
Woodbin | 9. prosince 2013

největší kecalové

Anonym Anonym
JeLito JeLito
cbvcxy cbvcxy
adam adam

K47i © 2002 - 2014 K. aka Kaja47