přihlásit se
k47.cz
Nyní pod dohledem Systémového Supervizora

Scala - Booleovská kompozice funkcí

autor: kaja47 - CC by-sa - publikováno: - sekce obsah » programování #2371
štítky: , a
Tento článek obsahuje zhruba 500 slov a jeho přečtení Vám zabere 2 až 5 minut

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

@spazef0rze http://t.co/rUh3R1sYen
@spazef0rze V PHP se to dá oháčkovat nějak takto: https://t.co/jyJMPONMov
@spazef0rze T_STRING je posloupnost znaků, T_CONSTANT_ENCAPSED_STRING je string literál. Potud je to konzistentní.
@spazef0rze Stejně tak nemůže mít jméno class, and, function nebo jakékoli jiné klíčové slovo. Divný je hlavně, že $a->list() je validní.

tadá

poslední články

Kdo nečte s námi, čte proti nám
článek | 30. dubna 2013
Oldboy
film | 13. dubna 2013
Jon Richardson vs. Sean Lock
článek | 4. dubna 2013
Zvuky!
článek | 29. března 2013
Co všechno neexistovalo, když jsem začínal s k47čkou
interní článek | 25. března 2013
Kdyby se někdo ptal, zapírej
| 17. března 2013
Horečka #4
povídka | 17. března 2013
Horečka #3
povídka | 17. března 2013
Horečka #2
povídka | 17. března 2013

poslední komentáře

Přeprava cestujících v Simutrans
Šimon-Erich Jelínek | 19. května 2013
Přeprava cestujících v Simutrans
Šimon-Erich Jelínek | 19. května 2013
Horečka #1
adam | 9. května 2013
Futurama
Saja | 21. března 2013
Skupinová samomluva 4
kaja47 | 16. března 2013

největší kecalové

Lisured Lisured
Daniel Daniel

K47i © 2002 - 2013 K. aka Kaja47