Funkcionalno programiranje kolska 201920 godina Letnji semestar Lekcija

  • Slides: 25
Download presentation
Funkcionalno programiranje Školska 2019/20 godina Letnji semestar

Funkcionalno programiranje Školska 2019/20 godina Letnji semestar

Lekcija 5: Komponvanje funkcija

Lekcija 5: Komponvanje funkcija

Sadržaj • Komponenta i komponovanje • Funkcije i kompozicija funkcija • Apstrakcija i kompozicija

Sadržaj • Komponenta i komponovanje • Funkcije i kompozicija funkcija • Apstrakcija i kompozicija

Komponenta i komponovanje • Komponenta je deo softvera koji se može višekratno koristiti kad

Komponenta i komponovanje • Komponenta je deo softvera koji se može višekratno koristiti kad god je potrebno ostvariti funkcionalnost koju ona implementira. • Kompozicija softvera je pravljenje i kombinovanje komponenti sa ciljem ostvarivanja potrebne funkcionalnosti. • Složenije funkcionalnosti ostvaruju se kombinovanjem komponenti – kao u građevinarstvu gde se kuća sastoji od prostorija, a prostorija se sastoje od zidova, podova, prozora, vrata. . . • To znači da su zidovi, podovi, prozori, vrata komponente koje možemo upotrebiti da napravimo prostoriju, a prostorija je komponenta koju možemo upotrebiti da napravimo kuću. • U softveru to znači da možemo kombinovati jednostavnije komponente u celine koje su opet komponente, ali veće i složenije.

Kompozicija funkcija u matematici • U matematici, kompozicija funkcija je operacija koja uzima dve

Kompozicija funkcija u matematici • U matematici, kompozicija funkcija je operacija koja uzima dve funkcije f i g i proizvodi funkciju h takvu da je h(x) = g(f(x)). • U toj operaciji, funkcija g se primenjuje na rezultat primene funkcije f na x. • f : X → Y g : Y → Z g(f(x)) = h(x) X → Z

Funkcije i kompozicija funkcija u FP-u • Funkcije se pojavljuju u različitim oblicima i

Funkcije i kompozicija funkcija u FP-u • Funkcije se pojavljuju u različitim oblicima i veličinama. A mi možemo da definišemo određene kombinacije funkcija koje daju novu kompozitnu funkciju koja će biti zgodna u različitim delovima programa. Taj proces zajedničkog korišćenje više funkcija se zove kompozicija funkcija. • Kompozicija u FP-u je modelovanje toka podataka kroz program. • To je koncept koji je fundamenta FP-a, jer se bez njega ne bi mogle deklarativno modelovati promene podataka i stanja. • Drugim rečima, sve ostalo u FP-u bi se srušilo bez kompozicije.

Kompozicija: modelovanje toka podataka kroz program • Ako možemo da definišemo kompoziciju dve funkcije,

Kompozicija: modelovanje toka podataka kroz program • Ako možemo da definišemo kompoziciju dve funkcije, možemo jednostavno da nastavimo i podržimo kompoziciju proizvoljnog broja funkcija. Vizualizacija toka podataka izgleda ovako: final. Value <-- func 1 <-- func 2 <--. . . <-- func. N <-- orig. Value • Znači, plazi se od originalne vrednosti kao ulaza u prvu (ili poslednju? ) funkciju i zatim se izlazi fukcija prosleđuju sledećoj funkciji u kompoziciji dok se ne dođe do poslednje (prve? ) funkcije u kompoziciji

Kompozicija funkcija: funkcija compose (. . . fns) function compose(. . . fns) {

Kompozicija funkcija: funkcija compose (. . . fns) function compose(. . . fns) { return function composed(result){ // kopiraj niz funkcija var list = [. . . fns]; // alert (' list = ' + list) while (list. length > 0) { // uzmi funkciju sa kraja liste i izvrši je result = list. pop()( result ); } return result; }; }

compose (. . . fns) - streličasta sintaksa // ES 6 => sintaksa var

compose (. . . fns) - streličasta sintaksa // ES 6 => sintaksa var compose = (. . . fns) => result => { var list = [. . . fns]; while (list. length > 0) { // uzmi funkciju sa kraja // liste i izvrši je result = list. pop()( result ); } return result; };

Kompozicija: Primer 1 let f 1 = (value) => return (value + }; let

Kompozicija: Primer 1 let f 1 = (value) => return (value + }; let f 2 = (value) => return (value + }; let f 3 = (value) => return value }; { 1) { 2) { let kompozicija = compose (f 1, f 2, f 3) let comp. Result = kompozicija (10) alert (' kompozicija je: ' + comp. Result)

Kako radi kompozicija: Primer 2 • Zadatak nam je da napravimo kod koji će

Kako radi kompozicija: Primer 2 • Zadatak nam je da napravimo kod koji će zadati tekst transformisati u listu pojedinačnih reči, među kojima nema ponovljenih reči. • Dakle, potrebno nam je sledeće • Funkcija koja će string rastaviti u niz reči – zvaćemo je words() • Funkcija koja će izbaciti duplikate - zvaćemo je unique()

Funkcija words() function words(str) { return String( str ). to. Lower. Case(). split( /s|b/

Funkcija words() function words(str) { return String( str ). to. Lower. Case(). split( /s|b/ ). filter( function alpha(v){ return /^[w]+$/. test( v ); }

Funkcija unique() function unique(list) { var uniq. List = []; for (let v of

Funkcija unique() function unique(list) { var uniq. List = []; for (let v of list) { // vrednost još nije u novoj listi? if (uniq. List. index. Of( v ) === -1 ) { uniq. List. push( v ); } } return uniq. List; }

Korišćenje var text = "Za komponovanje dve funkcije, proslediti  izlaz prvog poziva funkcije

Korišćenje var text = "Za komponovanje dve funkcije, proslediti izlaz prvog poziva funkcije kao ulaz drugom pozivu funkcije. "; // Prvi način pozivanja var words. Found = words(text); var words. Used = unique(words. Found); alert (" Prvi način pozivanja daje: " + words. Used) // Drugi način pozivanja var words. Used 1 = unique( words(text)); var words. Used 1; alert (" Drugi način pozivanja daje: " + words. Used 1)

Komponovanje više funkcija: Primer 3 • Zadatak nam je sledeći: • da napravimo kod

Komponovanje više funkcija: Primer 3 • Zadatak nam je sledeći: • da napravimo kod koji će zadati tekst transformisati u listu pojedinačnih reči, među kojima nema ponovljenih reči, i gde je zapis svake reči duži od 4 slova. • Dakle, potrebno nam je sledeće • Funkcija koja će string rastaviti u niz reči – zvaćemo je words() • Funkcija koja će izbaciti duplikate - zvaćemo je unique() • Funkcija koja će “preskočiti” kratke reči – zvaćemo je skip. Short. Words(. . ).

Primer 3: funkcija skip. Short. Words(words) function skip. Short. Words(words) { var filtered. Words

Primer 3: funkcija skip. Short. Words(words) function skip. Short. Words(words) { var filtered. Words = []; for (let word of words) { if (word. length > 4) { filtered. Words. push( word ); } } return filtered. Words;

Primer 3: Prvo korišćenje var text = "To compose two functions together, pass the

Primer 3: Prvo korišćenje var text = "To compose two functions together, pass the output of the first function call as the input of the second function call. "; var bigger. Words = compose( skip. Short. Words, unique, words ); var words. Used = bigger. Words( text ); words. Used; // Ispis: // ["compose", "functions", "together", "output", "first", "function", "input", "second"]

Kompozicija sa fiksiranim argumentima • Možemo da napravimo desnu parcijalnu aplikaciju funkcije compose(. .

Kompozicija sa fiksiranim argumentima • Možemo da napravimo desnu parcijalnu aplikaciju funkcije compose(. . ) tako što fiksiramo drugi i treći argument (unique(. . ) i words(. . ), respektivno); ono što dobijemo zvaćemo filter. Words(. . ). • Na taj način smo dobili funkciju koja može na različite načine da dodatno interveniše nad nizom reči bez duplikata (onim što se dobije fiksiranjem argumenata) prostim pozivanjem funkciju filter. Words(. . ) sa odgovarajućim prvim argumentom.

Primer 3: Drugo korišćenje var text = "To compose two functions together, pass the

Primer 3: Drugo korišćenje var text = "To compose two functions together, pass the output of the first function call as the input of the second function call. "; var filter. Words = partial. Right( compose, unique, words ); var bigger. Words = filter. Words( skip. Short. Words ); var bigger. Words. Found = bigger. Words( text ); bigger. Words. Found; // Ispis: // ["compose", "functions", "together", "output", "first", "function", "input", "second"] var shorter. Words = filter. Words( skip. Long. Words ); var shorter. Words. Found = shorter. Words( text ); shorter. Words. Found; // Ispis: // ["to", "two", "pass", "the", "of", "call", "as"]

Funkcija skip. Long. Words(words) function skip. Long. Words(words) { var filtered. Words = [];

Funkcija skip. Long. Words(words) function skip. Long. Words(words) { var filtered. Words = []; for (let word of words) { if (word. length <= 4) { filtered. Words. push( word ); } } return filtered. Words; }

Komponovanje više funkcija: rekurzija • Možemo da definišemo compose(. . ) i koristeći rekurziju.

Komponovanje više funkcija: rekurzija • Možemo da definišemo compose(. . ) i koristeći rekurziju. • Rekurzivna definicija za compose(fn 1, fn 2, . . fn. N) izgledala bi ovako: compose(fn 1, fn 2, . . fn. N-1), fn. N );

Rekurzivna kompozicija: implementacija // Konvencionalna sintaksa function compose(. . . fns) { // pull

Rekurzivna kompozicija: implementacija // Konvencionalna sintaksa function compose(. . . fns) { // pull off the last two arguments var [ fn 1, fn 2, . . . rest ] = fns. reverse(); var composed. Fn = function composed(. . . args){ return fn 2( fn 1(. . . args ) ); }; if (rest. length == 0) return composed. Fn; return compose(. . . rest. reverse(), composed. Fn ); } // Streličasta sintaksa var compose = (. . . fns) => { // pull off the last two arguments var [ fn 1, fn 2, . . . rest ] = fns. reverse(); var composed. Fn = (. . . args) => fn 2( fn 1(. . . args ) ); if (rest. length == 0) return composed. Fn; return compose(. . . rest. reverse(), composed. Fn ); };

Kompozicija inverznim redosledom • Redosled navođenja argumenata funkcija vs. redosled njihove primene • To

Kompozicija inverznim redosledom • Redosled navođenja argumenata funkcija vs. redosled njihove primene • To je obrnuto • Zato se uvodi sekvenca, odnosno pajp (pipe) gde se funkcije navode baš po redosledu primene

Funkcija pipe(. . . fns) function pipe(. . . fns) { return function piped(result){

Funkcija pipe(. . . fns) function pipe(. . . fns) { return function piped(result){ var list = [. . . fns]; while (list. length > 0) { // uzmi prvu funkciju iz liste i izvrši je result = list. shift()( result ); } return result; }; }

Funkcija pipe(. . . fns) • Funkcija pipe(. . . fns) je prosto izokretanje

Funkcija pipe(. . . fns) • Funkcija pipe(. . . fns) je prosto izokretanje argumenata funkcije compose(. . . fns) : var pipe = reverse. Args( compose ); function reverse. Args(fn) { return function args. Reversed(. . . args){ return fn(. . . args. reverse() ); }; }