Pub.ro



Facultatea de Electronica Telecomunica?ii si Tehnologia Informa?ieiProgramarea func?ional? ?n JavaScriptStuden?i: Profesor coordonator:Dun?ren?u Radu Florin Dr. Ing. ?tefan St?ncescuDun? Robert441ACuprins:1. Introducere (Dun?ren?u Radu)Importan?a program?rii func?ionale2. Limbaje de programare func?ional? (Dun?ren?u Radu)AvantajeLucrul cu func?iiFunc?iile IIFE ?i ClosuresFunc?ii de ordin superiorFunc?ii pureFunc?ii anonime?nl?n?uirea metodelor RecursivitateEvaluare lene??Folosirea tehnicilor func?ionale in JavaScriptExemple practice (Dun? Robert)3. Concluzii (Dun? Robert)Limbaje func?ionale vs orientate pe obiectEvolu?ia Limbajelor de Programare4. BibliografieAbstractCum software-ul devine din ce ?n ce mai complex, este cu at?t mai important s? fie organizat c?t mai bine. Software-ul care este bine structurat este u?or de scris, ?n?eles ?i depanat, ?i ofer? o colec?ie de module ce pot fi refolosite pentru a reduce timpul ?i costurile de produc?ie viitoare. ?n aceast? lucrare se dore?te eviden?iere diferen?ei fa?? de celelalte stilului de programare ?i avantajele folosiri unui stil func?ional.1 IntroducereNumele de programare func?ional? provine din faptul c? are ca opera?ie fundamental? aplicarea de func?ii pe argumente. Programul principal este scris ca o func?ie care prime?te ca argumente parametrii de intrare ai programului ?i returneaz? rezultatul programului. De obicei func?ia principal? este definit? ca alte func?ii, care la r?ndul lor sunt definite de alte func?ii, p?n? c?nd func?iile de la nivelul de jos sunt primitive de limbaj. Toate aceste func?ii de jos sunt asem?n?toare func?iilor matematice.Caracteristicile ?i avantajele stilului func?ional sunt pe scurt urm?toarele. Programele func?ionale nu con?in instruc?iuni de atribuire, o variabil? odat? ce a primit o valoare nu mai poate fi modificat?. Mai general, programele func?ionale nu pot avea efecte secundare asupra altor programe. O apelare de func?ie ?ntotdeauna calculeaz? numai rezultatul s?u. Aceasta abordare elimin? o mare parte a bug-urilor ?i de asemenea face ordonarea func?iilor irelevant?, aduc?nd posibilitatea apel?rii oric?nd a unei func?ii indiferent de stare, ceea ce duce la eliminarea flow controlului de c?tre programator. Importan?a program?rii func?ionaleScopul principal al program?rii orientate pe obiecte este de a sparge problema ?n p?r?i, exemplu figura 1. Figur? SEQ Figur? \* ARABIC 1.1 Problem? spart? ?n componente obiect-orientateDe asemenea, aceste p?r?i pot fi reunite pentru a forma p?r?i mai mari dup? cum este ilustrat ?n figura 2.Figur? SEQ Figur? \* ARABIC 2. Obiectele sunt compuse pentru a forma obiecte mai mari ?n func?ie de leg?turile ?i valoarea p?r?ilor este descris un sistem ?n figura 3.Figur? SEQ Figur? \* ARABIC 3. Diagrama de interac?iune a unui sistem obiect orientat Pentru compara?ie teoretic? este ilustrat ?n figura 4 abordarea rezolv?rii unei probleme abord?nd stilul func?ional tot prin spargerea problemei ?n p?r?i. Stilul OO sparge problema ?n grupuri de obiecte pe c?nd abordarea func?ional? sparge aceia?i problem? ?n grupuri de func?ii.?ntr-un sistem OO, interac?iunea ?ntre obiecte cauzeaz? schimb?ri interne asupra fiec?rui obiect, ce duce la starea general? a unui sistem s? fie compus? din mai multe schimb?ri minore de st?ri. Aceste schimb?ri minore si inter legate formeaz? conceptual “o p?nz? de p?ianjen”. Cu cre?terea complexit??ii apare o confuzie legat? de rela?iile ?ntre obiecte ?i este necesar? o cunoa?tere a mai multor straturi pentru ad?ugarea a noi obiecte sau a unor propriet??i de sistem.Figur? SEQ Figur? \* ARABIC 4. Problem? spart? ?n p?r?i func?ionalePe de alt? parte, un sistem construit folosind stilul func?ional minimizeaz? modific?rile de stare. Deci, pentru a ad?uga o nou? proprietate este nevoie de nevoie de a ?n?elege cum func?iile pot s? existe ?i func?ioneze ?n contextul de date nedistructive si imutabile. Programarea func?ional? nu este pentru a elimina schimb?rile de stare ci pentru a le reduce. Javascript suport? ambele stiluri de programare ceea ce ?nseamn? c? un sistem poate fi ?i ar trebui creat folosind ambele stiluri. Figur? SEQ Figur? \* ARABIC 5. Func?ie compus? din mai multe func?ii2 Limbaje de programare func?ional?Limbajele de programare func?ional? sunt acele limbaje care faciliteaz? paradigma de programare func?ional? prin folosirea func?iilor de ordin superior, func?iilor pure ?i imutabilitatea datelor. ?n cazul ?n care un limbaj include caracteristici necesare pentru programarea func?ional?, atunci este un limbaj func?ional. ?n cele mai multe cazuri, stilul de programare determin? dac? un limbaj este func?ional sau nu.Programarea func?ional? nu se poate realiza in C sau Java. Acestea ?i multe alte limbaje nu con?in structurile necesare pentru a suporta aceast? paradigm?. Ele sunt orientate pur pe obiect ?i strict non-func?ionale. ?n acela?i timp, paradigma de programare orientat? pe obiecte nu poate fi aplicat? pe limbaje pur func?ionale cum ar fi Scheme, Haskell si Lisp. Exist? limbaje ce suport? ambele paradigme. Python este cel mai cunoscut limbaj in acest caz, printre altele mai sunt ?i Ruby, Julia si Javascript. ?n cazul limbajului Javascript caracteristicile de programare func?ional? sunt ascunse.CaracteristiciImperativFunc?ionalStil de ProgramareEfectueaz? sarcini pas cu pas si gestioneaz? schimb?rile de stare Define?te problema si transform?rile necesare pentru g?sirea solu?ieiSchimb?ri de StareImportant?InexistenteOrdinea Execu?ieiImportant?Neimportant?Gestionarea controlului Bucle, condi?ionale ?i apeluri de func?iiApeluri de func?ii ?i recursiuneUnitatea de manipulare primar?Structuri ?i clase de obiecteFunc?ii ca obiecte ?i seturi de date Sintaxa limbajului trebuie s? permit? folosirea anumitor structuri de date cum ar fi func?ii anonime ?i sisteme de tip dedus. Esen?ial pentru un limbaj func?ional este permiterea folosirii calcului lambda. De asemenea strategia de evaluarea a interpretorului trebuie s? fie non-strict? ?i cu execu?ie ?nt?rziat? care permite existen?a structurilor de date imutabile ?i evaluarea lene??.Avantaje:Programele func?ionale sunt mai curate, simple ?i mici. Aceasta duce la simplificarea depan?rii, test?rii ?i mentenan?ei. Spre exemplu, fie o func?ie ce converte?te un vector cu 2 dimensiuni ?ntr-un vector cu o dimensiune. At?t func?ia scris? imperativ, Code 1, c?t ?i func?ia scris? func?ional, Code 2, primesc acela?i argument de intrare ?i returneaz? acela?i lucru. Se poate observa cum exemplul func?ional este mai concis ?i curat.center3903641Code 1. Stil func?ionalCode 1. Stil func?ional3981012899233varmerge2dArrayIntoOne2 = function(arrays) {return arrays.reduce( function(p,n){return p.concat(n);});};020000varmerge2dArrayIntoOne2 = function(arrays) {return arrays.reduce( function(p,n){return p.concat(n);});};3956052655570Code 2. Stil ImperativCode 2. Stil Imperativ395605370840function merge2dArrayIntoOne(arrays) {var count = arrays.length,merged = new Array(count),c = 0,i = 0,j = 0;for (i; i < count; ++i) {for (j, jlen = arrays[i].length; j < jlen; ++j) {merged[c++] = arrays[i][j];}}return merged}020000function merge2dArrayIntoOne(arrays) {var count = arrays.length,merged = new Array(count),c = 0,i = 0,j = 0;for (i; i < count; ++i) {for (j, jlen = arrays[i].length; j < jlen; ++j) {merged[c++] = arrays[i][j];}}return merged}Programarea func?ional? implic? spargerea problemei ?n p?r?i. Asta ?nseamn? c? codul este modular. Programele modulare sunt clar specificate, u?or de depanat ?i ?ntre?inut. Faciliteaz? testarea deoarece fiecare modul in parte poate fi testat independent.Programele func?ionale ?mp?rt??esc o varietate de func?ii ajut?toare datorit? modularit??ii program?rii func?ionale. Spre exemplu, o func?ie ce caut? prin liniile de configurare ale unui fi?ier poate s? fie folosit? ?i pentru c?utarea ?ntr-o structur? de date de tip hash table.Reduce inter-dependen?ele. Deoarece un programator func?ional scrie func?ii de tip prima clas?, func?ii de ordin superior ?i func?ii pure ce sunt complet independente ?i f?r? efecte secunde asupra variabilelor globale, interdependen?ele sunt reduse. Modificarea unei func?ii nu va schimba alta func?ie at?t timp c?t se p?streaz? input-urile si output-urile. Lucrul cu func?iiPrincipiul program?rii func?ionale este de a descompune o problem? ?ntr-un set de func?ii. De multe ori func?iile sunt legate ?mpreun?, imbricate reciproc ?i tratate ca cet??eni de prim? clas?. Framework-urile jQuery ?i Node.js sunt printre cele mai cunoscute tehnologii ce folosesc aceste tehnici. 76203126105Code 3. Exemplul 1Code 3. Exemplul 1right985520varobj1 = {value: 1},obj2 = {value: 2},obj3 = {value: 3},values = [];function accumulate(obj) {values.push(obj.value);}accumulate(obj1);accumulate(obj2);console.log(values); // Output: [obj1.value, obj2.value]020000varobj1 = {value: 1},obj2 = {value: 2},obj3 = {value: 3},values = [];function accumulate(obj) {values.push(obj.value);}accumulate(obj1);accumulate(obj2);console.log(values); // Output: [obj1.value, obj2.value]Pentru a explica ?i demonstra avantajele program?rii func?ionale vom folosi un exemplu practic. Dorim s? alc?tuim o list? de valori care sunt atribute generice ale unor obiecte. Aceste obiecte pot fi orice: date, obiecte HTML, etc. Codul de mai sus func?ioneaz? dar este volatil. Orice cod poate s? modifice lista values f?r? s? apeleze func?ia acumulate(). Dac? nu este ini?ializat la ?nceput lista cu valoarea goal?, [], atunci codul nu o s? func?ioneze. Dac? variabila este declarat? ?nauntrul func?iei atunci ea nu poate fi modificat? de niciun alt cod. Pentru a rezolva aceasta problem? este necesar? folosirea unei func?ii de tip IIFE (func?ie auto-apelat?).Func?iile IIFE ?i ClosuresPrin folosirea unei func?ii IIFE putem s? return?m o func?ie ce returneaz? la r?ndul ei valorile din lista values. Variabilele din func?ie sunt disponibile pentru modificare numai ?n interiorul func?iei.03044190Code SEQ Code \* ARABIC 4. IIFE & ClosureCode SEQ Code \* ARABIC 4. IIFE & Closureleft184150var ValueAccumulator = function() {var values = [];var accumulate = function(obj) {if (obj) {values.push(obj.value);return values;}else {return values;}};return accumulate;};var accumulator = ValueAccumulator();accumulator(obj1);accumulator(obj2);console.log(accumulator());// Output: [obj1.value, obj2.value]020000var ValueAccumulator = function() {var values = [];var accumulate = function(obj) {if (obj) {values.push(obj.value);return values;}else {return values;}};return accumulate;};var accumulator = ValueAccumulator();accumulator(obj1);accumulator(obj2);console.log(accumulator());// Output: [obj1.value, obj2.value]Principul ?ine de domeniul variabilelor. Lista values este disponibil? ?n interiorul func?iei accumulate() chiar ?i atunci c?nd func?ia este apelat? din afara domeniului ei. Aceasta este un closure. Closures ?n javascript sunt func?ii ce au acces la domeniul p?rintelui chiar ?i atunci c?nd acesta este ?nchis. Closures sunt o caracteristic? a tuturor limbajelor func?ionale. Limbajele imperative tradi?ionale nu permit existen?a lor din motive de securitate ?i gestiunea proast? a memoriei.Func?ii de ordin superiorFunc?iile IIFE sunt de fapt o form? de func?ii de ordin superior. Func?iile de ordin superior sunt func?ii care fie iau o alta func?ie ca intrare sau returneaz? o func?ie ca ie?ire.Func?iile de ordin superior nu sunt des ?nt?lnite ?n practic?. ?n timp ce un programator imperativ ar putea folosi o bulc? pentru a repeta o matrice, un programator func?ional ar avea cu totul alt? abordare. Prin utilizarea unei func?ii de ordin superior , matricea poate fi prelucrat? prin aplicarea unei func?ii pe fiecare element al matricei pentru a crea o matrice noua.Aceasta este ideea central? a paradigmei de programare func?ional?. Func?iile de ordin superior permit programatorului sa transmit? logica altor func?ii, la fel ca la obiecte.76201881505Code SEQ Code \* ARABIC 5. Func?ie de ordin superiorCode SEQ Code \* ARABIC 5. Func?ie de ordin superiorright748030// folosim forEach() pentru a itera lista si apelarea// func?iei de reapelare, accumulator, pentru fiecare elementvar accumulator2 = ValueAccumulator();var objects = [obj1, obj2, obj3]; objects.forEach(accumulator2);console.log(accumulator2());020000// folosim forEach() pentru a itera lista si apelarea// func?iei de reapelare, accumulator, pentru fiecare elementvar accumulator2 = ValueAccumulator();var objects = [obj1, obj2, obj3]; objects.forEach(accumulator2);console.log(accumulator2());Pentru a observa aceasta facilitate, vom folosi func?ia ValueAcumulator() din sec?iunea anterioar?.Func?ii pureFunc?iile pure sunt acele func?ii ce returneaz? o valoare calculat? numai din argumentele ei. Variabilele globale ?i cele din st?ri p?rinte nu pot fi utilizare, nu exist? efecte secundare. Cu alte cuvinte, argumentele nu pot fi alterate. Prin urmare, func?iile pure sunt utilizare numai pentru valoarea lor de ie?ire.Un exemplu de func?ie pur? este o func?ie matematic?. Math.sqrt(4) o s? returneze mereu valoarea 2, nu are set?ri sau stare proprie ?i nu o s? aib? niciodat? efecte secundare.Func?iile pure sunt adev?rata interpretare a termenului matematic pentru func?ie, o rela?ie ?ntre intr?ri ?i ie?iri. Sunt simple, u?or de ?n?eles ?i sunt reutilizabile. Deoarece sunt independente, func?iile pure se pot reutiliza frecvent. Pentru a ar?ta asta vom compara o func?ie pur? cu una non-pur?.right3889552Code SEQ Code \* ARABIC 6. Func?ie non-pur? vs func?ie pur?Code SEQ Code \* ARABIC 6. Func?ie non-pur? vs func?ie pur?right413// func?ie ce afi?eaz? un mesaj pe centrul ecranuluivar printCenter = function(str) {var elem = document.createElement("div");elem.textContent = str;elem.style.position = 'absolute';elem. = window.innerHeight/2+"px";elem.style.left = window.innerWidth/2+"px";document.body.appendChild(elem);};printCenter('hello world');// func?ie pur? care face acela?i lucruvar printSomewhere = function(str, height, width) {var elem = document.createElement("div");elem.textContent = str;elem.style.position = 'absolute';elem. = height;elem.style.left = width;return elem;};document.body.appendChild(printSomewhere('hello world',window.innerHeight/2)+10+"px",window.innerWidth/2)+10+"px"));020000// func?ie ce afi?eaz? un mesaj pe centrul ecranuluivar printCenter = function(str) {var elem = document.createElement("div");elem.textContent = str;elem.style.position = 'absolute';elem. = window.innerHeight/2+"px";elem.style.left = window.innerWidth/2+"px";document.body.appendChild(elem);};printCenter('hello world');// func?ie pur? care face acela?i lucruvar printSomewhere = function(str, height, width) {var elem = document.createElement("div");elem.textContent = str;elem.style.position = 'absolute';elem. = height;elem.style.left = width;return elem;};document.body.appendChild(printSomewhere('hello world',window.innerHeight/2)+10+"px",window.innerWidth/2)+10+"px"));?n timp ce func?ia non-pur? se bazeaz? pe starea obiectului fereastr? pentru a calcula ?n?l?imea ?i l??imea, func?ia pur? este autonom? ?i cere ca aceste valori s? fie furnizate ca argumente. Acest fapt permite ca mesajul s? fie tip?rit oriunde, iar acest lucru face ca func?ia s? fie mult mai versatil?.266702781935Code SEQ Code \* ARABIC 7. Combinarea unei func?ii pure cu alte tehnici func?ionaleCode SEQ Code \* ARABIC 7. Combinarea unei func?ii pure cu alte tehnici func?ionaleright1216660var messages = ['Hi', 'Hello', 'Sup', 'Hey', 'Hola'];messages.map(function(s,i){return printSomewhere(s, 100*i*10, 100*i*10);}).forEach(function(element) {document.body.appendChild(element);});020000var messages = ['Hi', 'Hello', 'Sup', 'Hey', 'Hola'];messages.map(function(s,i){return printSomewhere(s, 100*i*10, 100*i*10);}).forEach(function(element) {document.body.appendChild(element);});?n timp ce func?ia non-pur? poate p?rea op?iunea mai u?oar?, pentru c? efectueaz? ad?ugarea ?n sine ?n loc de a ?ntoarce un element, func?ia pur? printSomewhere() ?i valoarea ei returnat? se combin? mai u?or cu alte tehnici func?ionale de programare.?n cazul ?n care func?iile sunt pure ?i nu se bazeaz? pe stare sau mediu, nu ne pas? dac? sunt sunt sau nu calculate. Aceasta face parte din principul de evaluare lene??.Func?ii anonime76203592195Code SEQ Code \* ARABIC 8. Exemplu de func?ie anonim?Code SEQ Code \* ARABIC 8. Exemplu de func?ie anonim?right1451610function powersOf(x) {return function(y) {// aceasta este o func?ie anonim?!!return Math.pow(x,y);};}powerOfTwo = powersOf(2);console.log(powerOfTwo(1)); // 2console.log(powerOfTwo(2)); // 4console.log(powerOfTwo(3)); // 8powerOfThree = powersOf(3);console.log(powerOfThree(3)); // 9console.log(powerOfThree(10)); // 59049020000function powersOf(x) {return function(y) {// aceasta este o func?ie anonim?!!return Math.pow(x,y);};}powerOfTwo = powersOf(2);console.log(powerOfTwo(1)); // 2console.log(powerOfTwo(2)); // 4console.log(powerOfTwo(3)); // 8powerOfThree = powersOf(3);console.log(powerOfThree(3)); // 9console.log(powerOfThree(10)); // 59049Un alt beneficiu de a trata func?iile ca obiecte de prim? clas? este apari?ia func?iilor anonime. Dup? cum implic? numele lor, func?iile anonime sunt func?ii f?r? nume. Ele permit programatorului sa defineasc? logica ad-hoc, dup? cum este necesar. Beneficiul lor ?l reprezint? comoditatea, dac? o func?ie este men?ionat? o singur? dat? nu mai este nevoie pentru a folosi o variabil?.Func?ia returnat? nu trebuie numit?, ea poate fi folosit? oriunde ?nafara func?iei powerOf(), deci este o func?ie anonim?.Un alt exemplu ce folose?te func?ia acumulator de mai devreme scris? folosind o func?ie pur?, de ordin superior ?i anonim?. De asemenea este auto-apelat?, indicat de structura (function() {…}) (), parantezele de dup? func?ia anonim? face ca aceasta sa fie apelat? imediat. ?n exemplul de mai jos, lista values este asignat? ie?irii func?iei anonime.Un dezavantaj al func?iilor anonime este dificultatea de a fi identificate ?n stiva ceea ce face depanarea mai dificil?.38103147695Code SEQ Code \* ARABIC 9. Func?ia acumulator scris? ca func?ie anonim?Code SEQ Code \* ARABIC 9. Func?ia acumulator scris? ca func?ie anonim?3810118varobj1 = {value: 1},obj2 = {value: 2},obj3 = {value: 3};var values = (function() {// func?ie anonim?var values = [];return function(obj) {// func?ie anonim?if (obj) {values.push(obj.value);return values;}else {return values;}}})(); // auto apelat?console.log(values(obj1)); // Returns: [obj.value]console.log(values(obj2)); // Returns: [obj.value, obj2.value]020000varobj1 = {value: 1},obj2 = {value: 2},obj3 = {value: 3};var values = (function() {// func?ie anonim?var values = [];return function(obj) {// func?ie anonim?if (obj) {values.push(obj.value);return values;}else {return values;}}})(); // auto apelat?console.log(values(obj1)); // Returns: [obj.value]console.log(values(obj2)); // Returns: [obj.value, obj2.value]?nl?n?uirea metodelor 36773199514Code SEQ Code \* ARABIC 10. ?nl?n?uirea metodelorCode SEQ Code \* ARABIC 10. ?nl?n?uirea metodelor3810985520// imperativarr = [1,2,3,4];arr1 = arr.reverse();arr2 = arr1.concat([5,6]);arr3 = arr2.map(Math.sqrt);// func?ionalconsole.log( [1,2,3,4].reverse().concat([5,6]).map(Math.sqrt));arr.zip([11,12,13,14).map(function(n){return n*2});// Output: 2, 22, 4, 24, 6, 26, 8, 2800// imperativarr = [1,2,3,4];arr1 = arr.reverse();arr2 = arr1.concat([5,6]);arr3 = arr2.map(Math.sqrt);// func?ionalconsole.log( [1,2,3,4].reverse().concat([5,6]).map(Math.sqrt));arr.zip([11,12,13,14).map(function(n){return n*2});// Output: 2, 22, 4, 24, 6, 26, 8, 28?nl?n?uirea metodelor este des ?nt?lnit? ?n Javascript. Aceast? tehnic? este folosit? pentru simplificare codului atunci c?nd mai multe func?ii sunt aplicate pe acela?i obiect consecutiv.RecursivitateRecursivitatea este cea mai faimoas? tehnic? func?ional?. O func?ie recursiv? este aceea func?ie ce se apeleaz? reciproc. C?nd o func?ie se reapeleaz? reciproc ea se comport? ca o bucl?, adic? execut? aceia?i por?iune de cod de mai multe ori dar ?i ca o stiv? de func?ii. ?n lucrul cu func?ii recursive trebuie evitat? bucla infinit? sau recursivitatea infinit?, deci ca ?i ?n cazul buclelor se folose?te o condi?ie de stop numit? caz de baz?.Este posibil? convertirea oric?rei bucle ?ntr-un algoritm recursiv ?i invers. ?n unele cazuri algoritmii recursivi sunt necesari pentru situa?ii care difer? foarte mult de cele ?n care buclele sunt adecvate.38102698750Code SEQ Code \* ARABIC 11. Parcurgerea unui arbore recursivCode SEQ Code \* ARABIC 11. Parcurgerea unui arbore recursiv3810989330var getLeafs = function(node) {if (node.childNodes.length == 0) {// caz de baz?return node.innerText;}else {// caz recursivreturn node.childNodes.map(getLeafs);}}020000var getLeafs = function(node) {if (node.childNodes.length == 0) {// caz de baz?return node.innerText;}else {// caz recursivreturn node.childNodes.map(getLeafs);}}Un bun exemplu este parcurgerea unui arbore. Este u?or de realizat parcurgerea lui folosind un algoritm recursiv, pe c?nd folosind o bucl? gradul de complexitate cre?te.Evaluarea lene??Evaluarea lene??, numit? ?i evaluare non-strict?, apelare cu necesitate sau execu?ie am?nat?, este o strategie de evaluare, care a?teapt? p?n? c?nd este necesar pentru a calcula valoarea rezultat? a func?iei ?i este deosebit de util? pentru programarea func?ional?. Spre exemplu, este clar c? linia de cod x = func() apeleaz? pe x s? fie atribuit valorii returnate de func?ia func(). Cu ce este egal x nu conteaz? p?n? la necesitatea acestuia. A?tept?nd apelarea func?iei func() p?n? c?nd este nevoie de x se nume?te evaluare lene??.Aceast? strategie poate s? creasc? performan?ele, mai ales c?nd sunt folosite metode ?nl?n?uite ?i liste. Un alt beneficiu al evalu?rii lene?e ?l reprezint? seriile infinite. Deoarece nimic nu este calculat p?n? nu este nevoie de el este posibil? urm?toarea scriere.Acest beneficiu deschide u?a unor noi posibilit??i cum ar fi109855742315Code SEQ Code \* ARABIC 12. Serii infiniteCode SEQ Code \* ARABIC 12. Serii infinite109855184150var infinateNums = range(1 to infinity);var tenPrimes = infinateNums.getPrimeNumbers().first(10);020000var infinateNums = range(1 to infinity);var tenPrimes = infinateNums.getPrimeNumbers().first(10);: execu?ie asincron?, paralelizare ?i compozi?ie, printre multe altele.Folosirea tehnicilor func?ionale in JavaScript-69855842635Code SEQ Code \* ARABIC 13. Datele de pe serverCode SEQ Code \* ARABIC 13. Datele de pe server-69851687830var data = { result: "SUCCESS", interfaceVersion: "1.0.3", requested: "10/17/2013 15:31:20". lastUpdated: "10/16/2013 10:52:39", tasks: [ {id: 104, complete: false, priority: "high", dueDate: "11/29/2013", member: "Scott", title: "Do something", created: "9/22/2013"}, {id: 105, complete: false, priority: "medium", dueDate: "11/22/2013", member: "Lena", title: "Do something else", created: "9/22/2013"}, {id: 107, complete: true, priority: "high", dueDate: "11/22/2013", member: "Mike", title: "Fix the foo", created: "9/22/2013"}, {id: 108, complete: false, priority: "low", dueDate: "11/15/2013", member: "Punam", title: "Adjust the bar", created: "9/25/2013"}, {id: 110, complete: false, priority: "medium", dueDate: "11/15/2013", member: "Scott", title: "Rename everything", created: "10/2/2013"}, {id: 112, complete: true, priority: "high", dueDate: "11/27/2013", member: "Lena", title: "Alter all quuxes", created: "10/5/2013"} // , ... ]};020000var data = { result: "SUCCESS", interfaceVersion: "1.0.3", requested: "10/17/2013 15:31:20". lastUpdated: "10/16/2013 10:52:39", tasks: [ {id: 104, complete: false, priority: "high", dueDate: "11/29/2013", member: "Scott", title: "Do something", created: "9/22/2013"}, {id: 105, complete: false, priority: "medium", dueDate: "11/22/2013", member: "Lena", title: "Do something else", created: "9/22/2013"}, {id: 107, complete: true, priority: "high", dueDate: "11/22/2013", member: "Mike", title: "Fix the foo", created: "9/22/2013"}, {id: 108, complete: false, priority: "low", dueDate: "11/15/2013", member: "Punam", title: "Adjust the bar", created: "9/25/2013"}, {id: 110, complete: false, priority: "medium", dueDate: "11/15/2013", member: "Scott", title: "Rename everything", created: "10/2/2013"}, {id: 112, complete: true, priority: "high", dueDate: "11/27/2013", member: "Lena", title: "Alter all quuxes", created: "10/5/2013"} // , ... ]};O s? demonstr?m facilitatea program?rii func?ionale prin convertirea unui cod scris ?n stil imperativ ?n stil func?ional. O s? fie examinat? ?i o versiune orientat? pe obiecte dar se poate observa similitudinea cu cel imperativ numai structurarea este difer?. Exemplul nostru va fi o aplica?ie de organizare a sarcinilor, preluarea datelor se face de pe un server. Pentru a realiza aceast? aplica?ie este folosit? libr?ria Ramda.js Scopul va fi creare unei func?ii care accept? ca argument numele unei persoane(member), apoi preia datele de pe server ?i alege sarcinile care nu sunt finalizate de persoana respectiv?. Returneaz? id-ul sarcinilor, prioritatea, titlul ?i data de finalizare, sarcinile sunt sortate dup? data de finalizare.Deoarece preluarea datelor de pe server va fi asincron?, vom organiza codul cu promisiuni iar func?ia va ?ntoarce o promisiune care ar trebui s? rezolve o list? cu obiecte ce con?in propriet??ile necesare.247652546985Code SEQ Code \* ARABIC 14. Rezultatul de ie?ire al func?ieiCode SEQ Code \* ARABIC 14. Rezultatul de ie?ire al func?iei24765981710tasks: [ {id: 104, complete: false, priority: "high", dueDate: "11/29/2013", member: "Scott", title: "Do something", created: "9/22/2013"}, {id: 105, complete: false, priority: "medium", dueDate: "11/22/2013", member: "Lena", title: "Do something else", created: "9/22/2013"}, // , ...]020000tasks: [ {id: 104, complete: false, priority: "high", dueDate: "11/29/2013", member: "Scott", title: "Do something", created: "9/22/2013"}, {id: 105, complete: false, priority: "medium", dueDate: "11/22/2013", member: "Lena", title: "Do something else", created: "9/22/2013"}, // , ...]Pentru scopul demonstrativ, vor fi ignorate toate verific?rile de erori. ?ntr-un caz real, de produc?ie trebuie luate ?n considerare e?ecurile de comunicare cu serverul ?i scenarii de date gre?ite.-520707033260Code SEQ Code \* ARABIC 15. Abordarea imperativ? a problemeiCode SEQ Code \* ARABIC 15. Abordarea imperativ? a problemei-49663418332var getIncompleteTaskSummariesForMember_imperative = function(memberName) { return fetchData() .then(function(data) { return data.tasks; }) .then(function(tasks) { var results = []; for (var i = 0, len = tasks.length; i < len; i++) { if (tasks[i].member == memberName) { results.push(tasks[i]); } } return results; }) .then(function(tasks) { var results = []; for (var i = 0, len = tasks.length; i < len; i++) { if (!tasks[i].complete) { results.push(tasks[i]); } } return results; }) .then(function(tasks) { var results = [], task; for (var i = 0, len = tasks.length; i < len; i++) { task = tasks[i]; results.push({ id: task.id, dueDate: task.dueDate, title: task.title, priority: task.priority }) } return results; }) .then(function(tasks) { tasks.sort(function(first, second) { return first.dueDate - second.dueDate; }); return tasks; });};020000var getIncompleteTaskSummariesForMember_imperative = function(memberName) { return fetchData() .then(function(data) { return data.tasks; }) .then(function(tasks) { var results = []; for (var i = 0, len = tasks.length; i < len; i++) { if (tasks[i].member == memberName) { results.push(tasks[i]); } } return results; }) .then(function(tasks) { var results = []; for (var i = 0, len = tasks.length; i < len; i++) { if (!tasks[i].complete) { results.push(tasks[i]); } } return results; }) .then(function(tasks) { var results = [], task; for (var i = 0, len = tasks.length; i < len; i++) { task = tasks[i]; results.push({ id: task.id, dueDate: task.dueDate, title: task.title, priority: task.priority }) } return results; }) .then(function(tasks) { tasks.sort(function(first, second) { return first.dueDate - second.dueDate; }); return tasks; });};Exemplul imperativ de rezolvare a problemei-234955998845Code SEQ Code \* ARABIC 16. Prima parte a exemplului OOPCode SEQ Code \* ARABIC 16. Prima parte a exemplului OOP-23495519430// metoda principal?var getIncompleteTaskSummariesForMember_objectOriented = function(memberName) { return fetchData() .then(function(data) { var taskList = new TaskList(data.tasks); taskList.chooseByMember(memberName); taskList.chooseByCompletion(false); var newTaskList = taskList.getSummaries(); newTaskList.sort(new TaskListSorter("dueDate")); return newTaskList.tasks; });};var TaskList = (function() { var TaskList = function(/*Task[]*/ tasks) { this.tasks = tasks; }; TaskList.prototype.chooseByMember = function(memberName) { var results = []; for (var i = 0, len = this.tasks.length; i < len; i++) { if (this.tasks[i].member === memberName) { results.push(this.tasks[i]); } } this.tasks = results; }; TaskList.prototype.chooseByCompletion = function(completion) { var results = []; for (var i = 0, len = this.tasks.length; i < len; i++) { if (this.tasks[i].complete == completion) { results.push(this.tasks[i]); } } this.tasks = results; };020000// metoda principal?var getIncompleteTaskSummariesForMember_objectOriented = function(memberName) { return fetchData() .then(function(data) { var taskList = new TaskList(data.tasks); taskList.chooseByMember(memberName); taskList.chooseByCompletion(false); var newTaskList = taskList.getSummaries(); newTaskList.sort(new TaskListSorter("dueDate")); return newTaskList.tasks; });};var TaskList = (function() { var TaskList = function(/*Task[]*/ tasks) { this.tasks = tasks; }; TaskList.prototype.chooseByMember = function(memberName) { var results = []; for (var i = 0, len = this.tasks.length; i < len; i++) { if (this.tasks[i].member === memberName) { results.push(this.tasks[i]); } } this.tasks = results; }; TaskList.prototype.chooseByCompletion = function(completion) { var results = []; for (var i = 0, len = this.tasks.length; i < len; i++) { if (this.tasks[i].complete == completion) { results.push(this.tasks[i]); } } this.tasks = results; };Exemplu OOP de rezolvare a problemei-711208415655Code SEQ Code \* ARABIC 17. Exemplu de rezolvare abord?nd stilul func?ionalCode SEQ Code \* ARABIC 17. Exemplu de rezolvare abord?nd stilul func?ional-711206796405var propEq = use(pipe).over(get, eq); // TODO: move to library?var getIncompleteTaskSummariesForMemberFunctional = function(memberName) { return fetchData() .then(get('tasks')) .then(filter(propEq('member', memberName))) .then(reject(propEq('complete', true))) .then(map(pick(['id', 'dueDate', 'title', 'priority']))) .then(sortBy(get('dueDate')));};00var propEq = use(pipe).over(get, eq); // TODO: move to library?var getIncompleteTaskSummariesForMemberFunctional = function(memberName) { return fetchData() .then(get('tasks')) .then(filter(propEq('member', memberName))) .then(reject(propEq('complete', true))) .then(map(pick(['id', 'dueDate', 'title', 'priority']))) .then(sortBy(get('dueDate')));};-1187455492115Code SEQ Code \* ARABIC 18. A doua parte a exemplului OOPCode SEQ Code \* ARABIC 18. A doua parte a exemplului OOP-118745186055TaskList.prototype.getSummaries = function() { var results = [], task; for (var i = 0, len = this.tasks.length; i < len; i++) { task = this.tasks[i]; results.push({ id: task.id, dueDate: task.dueDate, title: task.title, priority: task.priority }) } return new TaskList(results); }; TaskList.prototype.sort = function(/*TaskListSorter*/ sorter) { this.tasks.sort(sorter.getSortFunction()); }; return TaskList;}());var TaskListSorter = (function() { var TaskListSorter = function(propName) { this.propName = propName; }; TaskListSorter.prototype.getSortFunction = function() { var propName = this.propName; return function(first, second) { return first[propName] < second[propName] ? -1 : first[propName] > second[propName] ? +1 : 0; } }; return TaskListSorter;}());020000TaskList.prototype.getSummaries = function() { var results = [], task; for (var i = 0, len = this.tasks.length; i < len; i++) { task = this.tasks[i]; results.push({ id: task.id, dueDate: task.dueDate, title: task.title, priority: task.priority }) } return new TaskList(results); }; TaskList.prototype.sort = function(/*TaskListSorter*/ sorter) { this.tasks.sort(sorter.getSortFunction()); }; return TaskList;}());var TaskListSorter = (function() { var TaskListSorter = function(propName) { this.propName = propName; }; TaskListSorter.prototype.getSortFunction = function() { var propName = this.propName; return function(first, second) { return first[propName] < second[propName] ? -1 : first[propName] > second[propName] ? +1 : 0; } }; return TaskListSorter;}());Este important de men?ionat diferen?ele ?ntre stilul imperativ ?i orientat pe obiect ?n exemplu, ?nafar? de c?teva cuvinte “this“, diferen?a ?ine de organizare. Con?inutul func?iilor este asem?n?tor, modul de organizare variaz?.3 ConcluziiLimbaje func?ionale vs orientate pe obiect?n aceast? lucrarea am discutat despre diversele moduri ?n care programarea func?ional? se leag? de principiile program?rii orientate pe obiecte. Programarea func?ional? accentueaz? puterea reutiliz?rii ?i compozi?ia de comportament prin func?ii de ordin superior. Nu exist? nici o ?ndoial? c? structurile de date imutabile ?mbun?t??esc siguran?a codului. De asemenea ceste caracteristici sunt disponibile ?i ?ntr-un context orientat pe obiect, tema comun? o reprezint? beneficiile ce sunt atinse sunt universale la ambele abord?ri. Ca programatori suntem ?ntotdeauna ?n c?utarea de a scrie cod mai sigur ?i de construi un comportament mai flexibil.Ideea program?rii func?ionale este procesul de g?ndire. Nu este necesar un nou limbaj de programare pentru a programa ?ntr-un stil func?ional, de?i unele caracteristici de limbaj ajut? uneori. Introducerea expresiilor lambda in Java 8 reprezint? un pas ?nainte pentru folosirea stilului func?ional ?n Java. ?n timp ce programarea orientat? pe obiecte a fost ?n mod tradi?ional despre ?ncapsularea datelor ?i al comportamentului, acum se adaug? suport pentru comportament independent mul?umit? ideilor din programarea func?ional?.Alte limbaje de programare cum ar fi Scala sau Haskell duc ideile func?ionale la un alt nivel. Scala ofer? un amestec de facilit??i func?ionale ?i obiecte orientate, ?n timp ce Haskell se concentreaz? pe programarea pur func?ional?.Dezvoltarea software const? ?n producerea de software de o calitate superioar? care satisface clien?ii ?i businessul. Un stil de programare func?ional poate atinge acest scop, dar nu este singurul.Evolu?ia Limbajelor de ProgramareUna dintre cele mai interesante tendin?e ?n timp ale limbajelor de programare este trecere treptat? la limbaje care sunt mai orientate pe obiecte ?i mai func?ionale. ?n anii 1980 limbajele procedurale au fost eliminate ?i limbajele func?ionale ?i orientate pe obiect au devenit populare.Destul de interesant, la ?nceputul cre?terii ?n popularitate, limbajele combinau stilurile func?ional cu obiect orientat. La ?nceput limbajul ideal pentru un stil obiect-orientat era Smalltalk. Smalltalk 80 permitea expresii lambda ?i libr?ria de colec?ii era de natur? func?ional?, existau opera?ii echivalente lui map, reduce ?i filter numai c? sub alte nume.Limbajul preferat pentru un stil func?ional era Common LISP. Acesta avea un sistem pentru orientarea pe obiecte numit CLOS (Common LISP Object System). Deci, ?n anii 1980, nu exista o cale pur? ?n care s? aplici aceste paradigme ?n produc?ie.?n timpul anilor 1990, programarea s-a schimbat. Programarea orientat? pe obiecte a devenit stilul dominant pentru a rezolva probleme business. Limbajele C++ ?i Java au crescut ?n popularitate. ?n anul 2001, conferin?a JavaOne a avut 28.000 de participan?i.?n ultimii ani, trendul s-a schimbat din nou. Limbajele populare de programare ies din tiparele pure de func?ionale sau obiect-orientate ?i migreaz? spre o abordare hibrid?. At?t C++ c?t ?i Java 8 au ad?ugat expresii lambda ?i faciliteaz? folosirea elementelor func?ionale al?turi de cele obiect-orientat.Noile limbaje ap?rute suport? mai multe paradigme din start. F# este un limbaj puternic ce faciliteaz? un stil func?ional ?i este la fel de bun ca C# ?n termeni de elemente obiect-orientate. Limbaje precum Ruby, Python ?i Groovy pot aborda stilul func?ional ?i obiect-orientat. Viitorul program?rii este hibrid, const? ?n alegerea celor mai bune caracteristici ?i idei din ambele stiluri pentru a rezolva o problem?.4 BibliografieFunctional programming in JavaScript – Dan MantylaFunctional JavaScript – Michael Fogus Why Functional Programming Matters – John HughesA practical introduction to functional programming – Mary Rose Cook Functional Programming – Scott SauyetFunctional Programming in Python – David MertzObject-Oriented vs. Functional Programming – Richard Warburton ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download