diff --git a/articles/2016/javascript-kompozice-a-currying.md b/articles/2016/javascript-kompozice-a-currying.md new file mode 100644 index 0000000000000000000000000000000000000000..4797c1eed3594308c0d91bfda640c6cec8f75df6 --- /dev/null +++ b/articles/2016/javascript-kompozice-a-currying.md @@ -0,0 +1,103 @@ +``` +title="Javascript: Kompozice a currying" +image="/images/javascript.jpg" +tags=["ProgramovánĂ", "javascript"] +``` + +O funkcionálnĂm programovanĂ se Ĺ™Ăká (jako i o spoustÄ› jinĂ˝ch vÄ›cĂ), Ĺľe vám musĂ +takzvanÄ› docvaknout, ale jakmile vám docvakne, tak to zaÄŤne dávat smysl a vy +budete v programovánĂ mnohem lepšĂ. MyslĂm si, Ĺľe mi dnes nÄ›co z funkcionálnĂho +programovanĂ docvaklo. + +MÄ›jme následujĂcĂ jednoduchĂ˝ Ăşkol: VytvoĹ™te funkci která: +- Z pole na vstupu, napĹ™.: `[1,2,3,4]` +- Vytvořà pole objektĹŻ `[{a: 1, b: 2}, {a: 3, b: 4}]` +- Tedy vezme dvojice prvkĹŻ z pole a vytvořà z nich objekt `{a, b}` + +Jak na to? ImperativnĂ zpĹŻsob by vypadal takto: + +``` +function transform(arr) { + var temp = [] + for(var i = 0; i < arr.length/2; i++) { + temp.push({a: arr[i*2], b: arr[i*2+1]}) + } + return temp +} + +transform([1,2,3,4]) +``` + +To nenĂ tak špatnĂ©, Ĺľe? Co se na tom dá zlepšit? ProblĂ©m je, Ĺľe to moc +nevyjadĹ™uje vÄ›tu "vezme dvojice prvkĹŻ z pole a vytvořà z nich objekt `{a, b}`". + +K pĹ™eloĹľenà části "vezme dvojice prvkĹŻ" lze s vĂ˝hodou pouĹľĂt funkce chunk +z knihovny [lodash](https://lodash.com/). A k části "vytvořà z nich objekt" se +dá pouĹľĂt funkce map (aĹĄ uĹľ lodash nebo standardnĂ verze). PouĹľĂvám FP verzi +knihovny lodash. + +``` +function transform(arr) { + return _.chunk(2, arr).map(function(el) { + return {a: el[0], b[1]} + }) +} + +transform([1,2,3,4]) +``` + +Tento kĂłd uĹľ je lepšà co se ÄŤitelnosti týče. ÄŚte se takto "rozsekej pole arr na +podpole velikosti 2 (funkce `_.chunk`) a potom kaĹľdou tuto část nahraÄŹ polem +`{a,b}` (funkce `.map`)" + +Ale co by se stalo pokud bychom chtÄ›li pouĹľĂt funkci map z knihovny lodash? +To by potĂ© vypadalo následovnÄ›: + +``` +function transform(arr) { + return _.map(function(el) { + return {a: el[0], b[1]} + }, _.chunk(2, arr)) +} + +transform([1,2,3,4]) +``` + +Neboli "namapuj to co vytvořà funkce `_.chunk(2, arr)`". Tomuto se Ĺ™Ăká kompozice +funkcĂ (function composition). Neboli jedna funkce dostane to, co druhá funkce +vracĂ. VytvářĂme tĂm takovĂ© pomyslnĂ© potrubĂ. `vstup -> chunk -> map -> vĂ˝stup`. +K tomuto se takĂ© dá pouĹľĂt funkce `_.flow` + +``` +var transform = _.flow( + _.chunk(2), + _.map((el)=> {return { + a:el[0], + b:el[1] + } +})) + +transform([1,2,3,4]) +``` + +Neboli pĹ™esnÄ› `vstup -> chunk -> map ([a,b] => {a,b}) -> vĂ˝stup`. Jak to ale funguje? + +Aby toto mohlo fungovat tak knihovna lodash (v FP verzi) implementuje koncept, +kterĂ©mu se Ĺ™Ăká 'currying'. Ten funguje tak, Ĺľe pokud funkce pĹ™ijĂmá nÄ›kolik +argumentĹŻ a my nÄ›kterĂ˝ vynecháme, tak mĂsto aby provedla danou akci, tak nám vrátĂ +funkci. + +DĹŻsledek tohoto je, Ĺľe `chunk(2, arr)` provede to samĂ© jako `chunk(2)(arr)` a to +je to samĂ© jako `var chunk2 = chunk(2); chunk(arr);`. Jednoduchá implementace +funkce flow by vypadala takto: + +``` +function flow(a, b) { + return function(args) { + b(a(args)) + } +} +``` + +To je vše! Ukázali jsme si, jak implementovat stejnou funkci ÄŤtyĹ™mi rĹŻznĂ˝mi zpĹŻsoby, +jak funguje currying a co je to kompozice funkcĂ.