Máte už plný zuby toho šílenýho povyku okolo funkcionálních jazyků?
Já teda jo. Myslím, že je načase sepsat pár rozumných důvodů, proč se
od něho držet dál. Funkcionální programování není pro
každého. To je důležité zmínit hned na začátku.
Pro jistotu, když píšu „staticky typovaný funkcionální jazyk,“ mám
na mysli jazyk, který i dokáže odvozovat typy, jeho datové struktury
nepodporují mutace, a podobné nesmysly. V praxi to znamená, že myslím
zcela nepraktické (akademické) jazyky jako je Haskell nebo jazyky z rodiny ML
(jako OCaml nebo F#).
Důvod první:
Nemám zájem sledovat poslední výstřelky
Jako většina programátorů, jsem přirozeně konzervativní a nerad se
učím nové věci. To je také důvod proč jsem si vybral kariéru v IT.
Rozhodně nejančím z každé žhavé novinky, jen proto, že všichni
frajeři se z ním můžou podělat. Já si radši počkám, až ten
výstřelek trochu dospěje a ukáže se trochu perspektivním. Pro mě tu není
funkcionální programování dostatečně dlouho, aby mě přesvědčilo, že
tu s námi ještě nějakou dobu bude.
Ano, někteří se nás mohou snažit přesvědčovat, že ML nebo Haskell tu
byly asi tak stejně dlouho jako naše staré známé oblíbené jazyky, jako je
Java nebo PHP, ale já o Haskellu, slyšel poprvé celkem nedávno, takže
s tímhle argumentem na mě nechoďte.
A podívejte na to batole, F#. Vždyť je teprve sedm let starý! Jistě, to
může být dost dlouhá doba pro geology, ale na internetu? Sedm let!? To je
skoro okamžik.
Tak, jak říkám, radši budu opatrný a ještě si pár dekád počkám,
jestli tu ještě tohle to funkcionální programování bude, nebo jestli se to
nakonec neukáže jako výstřelek doby.
Důvod druhý: Jsem placen od
řádky kódu
Já teda nevím jak vy, ale čím víc řádek napíšu, tím víc se cítím
produktivní. Pokud můžu za den vychrlit 500 řádků kódu, mám ze sebe
dobrý pocit. To byla dobře odvedená práce. Moje commity jsou velké a můj
šéf může jasně vidět, že jsem byl opravdu vytíženej.
Když porovnám kód napsaný ve funkcionálním jazyce s kódem ve starém
dobrém céčkovém jazyce, chybí tam tolik kódu, že mě to až děsí.
No, podívejte se sami na kód napsaný v povědomém jazyce:
public static class SumOfSquaresHelper
{
public static int Square(int i)
{
return i * i;
}
public static int SumOfSquares(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += Square(i);
}
return sum;
}
}
a porovnejte to s tímhle:
let square x = x * x
let sumOfSquares n = [1..n] |> List.map square |> List.sum
To je 17 řádek ku 2. Představte
si ten rozdíl, když to rozložíte na celý projekt! Kdybych takhle
přistupoval k psaní mých programů, moje produktivita by drasticky klesla.
Brrr, lepší si to ani nepředstavovat.
Důvod třetí: Miluju složené
závorky
A to taky dost nepobírám. Co je jako na těch jazycích, co se snaží
zbavit všech těch závorek? Jak je pak vůbec můžeme považovat za
opravdové programovací jazyky?
Pojďme si ukázat, co mám na mysli. Tady je kus kódu se starejma dobrejma
složenejma závorkama:
public class Squarer
{
public int Square(int input)
{
var result = input * input;
return result;
}
public void PrintSquare(int input)
{
var result = this.Square(input);
Console.WriteLine("Input={0}. Result={1}", input, result);
}
}
a tady obdobný kód bez složenejch závorek:
type Squarer() =
let Square input =
let result = input * input
result
let PrintSquare input =
let result = Square input
printf "Input=%i. Result=%i" input result
Vidíte to? Já teda nevím jak vám, ale mně ta druhá ukázka přijde dost
znepokojující, jako by tam něco důležitého chybělo. Ruku na srdce, jsem
celkem ztracený, když se mé oko nemůže odpíchnout od povědomých
složených závorek.
Důvod čtvrtý: Chci
vidět explicitní typy
Zastánci funkcionálního programování tvrdí, že odvozování typů,
dělá kód čistším, protože ho nemusíte pořád zanášet typovými
deklaracemi.
Abych byl upřímný, já typové deklarace vidět chci. Necítím se ve své
kůži, když nevidím jakého typu parametr přesně je. To je také důvod,
proč mám rád Javu.
Tady je signatůra funkce z nějakýho ML dialektu. Nejsou tam vůbec
žádný deklarace typů. Všechny jsou odvozený automagicky:
let GroupBy source keySelector =
...
A tady je signatura té samé funkce v C#, s explicitně
vyjádřenými typy:
public IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
...
Já teda nevím jak vám, ale mně se víc líbí druhá ukázka. Pro mě je
velice důležité, abych viděl, že ta funkce vrací
IEnumerable<IGrouping<TKey, TSource>>.
Tak určitě. Kompilátor jako zjistí, co je to za typ a upozorní mě,
když to nesedí, ale proč by to, proboha, měl dělat kompilátor? Od čeho
mám svůj mozek?
Přiznávám, že pokud pracujete s generiky, lambda výrazy a s funkcemi,
které vracejí funkce a s dalšíma cool novinkama, tak pak asi můžou být
typové declarace trochu fousaté a komplexní. Může to být trochu těžké,
napast správný typ. Ale na druhou stranu, existuje na to jednoduchý lék:
Nepoužívejte generika a nepředávejte si funkce. Vaše
signatury budou o dost jednodušší!
Důvod pátý: Rád opravuju bugy
Neznám nic napínavějšího než je lov – vystopovat a zlikvidovat
pořádnou bugu. A když najdu bugu v produkci, ještě líp, protože navíc
budu ještě za hrdinu.
Četl jsem, že se
staticky typovnými funkcionálními jazyky, je mnohem těžší
zanést chybu.
No tě pic.
Důvod šestý: V debuggeru
jsem jako doma
A když už jsem u toho lovení bugů. Většinu dne trávím v debuggeru,
krokováním kódu. Já vím, měl bych psát unit testy. Jenže to se
snadnějš řekne, než dělá…
Každopádně, podle všeho, pokud se vám
ve staticky typovaném funkcionálním jazyce podaří program zkompilovat,
většinou i funguje. Prej musíte většinu času zabít tím, aby jste
správně poladili typy, aby to pěkně sedělo a pak máte hotovo. Co je na tom
zábavného?
Což mě přivádí k…
Důvod sedmý:
Nechci přemýšlet nad každým detailem
Všechno to ladění typů a ujišťování se, že všechno perfektně
sedí, zní celkem nudně.
Dokonce jsem někde slyšel, že jste nucený přemýšlet o každém
možném hraničním případu, všech možných chybových stavech a já
nevím, co se ještě může zvrtnout. A to všechno od samého začátku.
Prostě nemůžeš být línej a nechat to na pozdějc.
Radši se zaměřuju na to, aby (většinou) všechno prošlo tak jak má a
bugy řeším, až když se ukážou.
Důvod osmý: Rád ověřuju null
Jsem velmi
svědomitý v případě ověřování null a to v každé
metodě. Celkem mě uspokojuje pocit, že vím, že můj kód je ve
výsledku úplně neprůstřelný.
void SomeMethod(SomeClass x)
{
if (x == null) { throw new ArgumentNullException(); }
x.DoSomething();
}
Kecám. Samozřejmě to nedělám úplně všude, to bych vůbec nic jinýho
neudělal.
Ale, nakonec se mi stalo jen jednou, že jsem musel řešit pád, kvůli
NRE. Ani jsme nepřišli o moc peněz za těch pár tejdnů, kdy
jsem hledal, kde je vlastně problém. Fakt nechápu, proč se z toho dělá
taková věda.
Důvod
devátý: Rád aplikuju návrhové vzory, kde je to možné
Poprvý jsem o návrhových vzorech četl v knize Návrhové vzory
(z nějakýho důvodu se občas označuje jako GoF vzory, ale fakt netušim
proč) a od tý doby je fakt pilně aplikuju na všechny problémy. Můj kód
pak vypadá líp a má „enterprise“ nádech. A to se mému
šéfovi líbí.
Ale ještě jsem ani náznakem neslyšel o nějakých vzorech ve
funkcionálním programování. Jak vůbec můžete udělat něco užitečnýho
bez Strategie, Abstraktní
továrny, Dekorátoru, Proxy nebo dalších?
Možná o nich funkcionální programátoři ani neslyšeli…
Důvod desátý: Je tam
příliš matematiky
Tady je další ukázka počítání mocnin. IMO je dost těžký pochopit,
o co vlastně jde, protože je tam sousta nesmyslných symbolů:
ss=: +/ @: *:
Dobře, omlouvám se, moje chyba, tohle je kód v J. Ale
stejně jsem viděl, jak je ten funkcionální kód plnej různých
<*> a >>= a vůbec takových divných
konceptů jako jsou „monády“ a „funktory“.
Fakt nechápu, proč tihle funkcionalisti nemohli nechat věci, který už
dobře znám – jasné symboly jako ++ nebo != a
jednoduché koncepty jako je „dědičnost“ a „polymorfismus“.
Shrnutí: Fakt to nechápu
Víte co? Fakt to nechápu. Nechápu, co by mohlo být na funkcionálním
programování užitečný.
Jediný oč žádám je, aby mi někdo ukázal skutečné
benefity na jedný stránce, místo chrlení příliš spousty nesourodých
informací.
Update: Tak jsem si přečetl tu stránku „vše co
potřebujete vědět na jediné stránce.“ Ale je to příliš
krátké a zjednodušující, aby mi to dávlo smysl. Fakt hledám něco, co
má
trochu hloubku, něco, co by mě fakt
chytlo.
A ne, fakt nemám chuť číst
tutoriály, hrát si
s ukázkama a psát vlastní kód. Chci tomu jen přijít na kloub, bez
toho, abych musel dělat všechny ty zbytečný věci.
Nechci měnit to, jak myslím, jen se chci naučit to nové
paradigma.
článek je volným překladem Ten
reasons not to use a statically typed functional programming language od
Scotta Wlaschina