concepte de programare functionala in javascript

36
Programare funcţională în Javascript Alexandru Badiu

Upload: alexandru-badiu

Post on 24-Jun-2015

2.591 views

Category:

Technology


5 download

DESCRIPTION

Prezentare de la Wurbe 14.

TRANSCRIPT

Page 1: Concepte de programare functionala in Javascript

Programare funcţională în JavascriptAlexandru Badiu

Page 2: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Conţinut

Ce este programarea funcţională?

Funcţii de ordin înalt

Funcţii anonime

Funcţii imbricate

Închideri

Currying

Page 3: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Funcţională?

Programarea funcţională este o paradigmă de programare

Se pune accent pe evaluarea expresiilor şi nu pe execuţia comenzilor

Expresiile sunt funcţii

Constante vs variabile

Lisp, Erlang, Haskell, OCaml

Dacă ai scris cod Javascript sau Ruby atunci probabil ai folosit concepte din programarea funcţională fără să ştii

Page 4: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Paradigme?

O paradigmă de programare e un stil de a programa

Concepte pentru elementele unui program (funcţii, variabile, obiecte etc)

Concepte pentru paşii unui calcul (evaluare, atribuire etc)

Un limbaj de programare poate oferi suport pentru mai multe paradigme

Page 5: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Procedurală

#include <stdio.h>#include <stdlib.h>

int main(void){ puts("Hello World!"); return EXIT_SUCCESS;}

Page 6: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?OO

class HelloWorld { static public void main( String args[] ) { System.out.println( "Hello World!" ); }}

Page 7: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Logică

?- write(”Hello World!”), nl.

Page 8: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Funcţională

(alert “Hello World!”)

Page 9: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Limbaje ezoterice

HAICAN HAS STDIO?VISIBLE "HAI WORLD!"KTHXBYE

Page 10: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?HTML

<p>HTML nu este un limbaj de programare.</p>

Page 11: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Javascript

Page 12: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii de ordin înaltDefiniţie

Funcţiile sunt de ordin înalt

Sunt obiecte

Au proprietăţi

Pot fi transmise altor funcţii

Pot fi întoarse ca rezultat

Pot fi create dinamic

Page 13: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii de ordin înaltExemplefunction say(what) { console.log(what);}

var say = function (what) { console.log(what);}

say('hello');// hellovar spune = say;spune('salut');// salut

say = function (what) { console.log('nu vreau');}

spune('ceva');// ceva

Page 14: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii de ordin înaltExemplevar gen_func = function (op) { switch (op) { case '+': return function () { var r = arguments[0]; for (var i=1; i<arguments.length; i++ ) r += arguments[i]; return r; } case '-': return function () { var r = arguments[0]; for (var i=1; i<arguments.length; i++ ) r -= arguments[i]; return r; } case '*': return function () { var r = arguments[0]; for (var i=1; i<arguments.length; i++ ) r *= arguments[i]; return r; } case '/': return function () { var r = arguments[0]; for (var i=1; i<arguments.length; i++ ) r /= arguments[i]; return r; } }}

var add = gen_func('+');add;// function () { var r = arguments[0]; for (var i = 1; i < arguments.length; i++) { r += arguments[i]; } return r; }add(1,2,3);// 6var mul = gen_func('*');mul(4,5,6);// 120

Page 15: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii de ordin înaltExemple

var compune = function (f, g) { return function (x) { return f(g(x)); }};

var a = function (x) { return x*x; };

var b = function (x) { return x/2; };

var c = compune(a, b);var d = compune(b, a);

c(6);// 9d(6);// 18

Page 16: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii anonimeDefiniţie

Funcţii fără nume

Folosite atunci când codul trebuie rulat o singură dată

Folosite la sortări, căutari

Folosite la evenimente

Page 17: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii anonimeExemple

(function (what) { console.log(what)}) ('functie anonima');

// functie anonima

( function (x) { if (x<2) return x; return x * arguments.callee(x - 1);}) (3);

// 6

Page 18: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii anonimeExemple

jQuery("div.autoo-more a").click(function(event) { mf = jQuery(this).parent().prev(); mf.toggle(); if (mf.css('display') == 'none') { jQuery(this).html('Mai multe &raquo;'); } else { jQuery(this).html('&laquo; Mai putine'); } return false;});

Page 19: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii anonimeExemplevar v = [ 6, 12, 19, 8, 40 ];v.sort();// 12,19,40,6,8

v.sort(function (x, y) { return x - y; });// 6,8,12,19,40

v.sort(function (x, y) { return y - x; });// 40,19,12,8,6

function Cauta(v, f){ for (var i = 0; i < v.length; i++) if (f(v[i])) { return i; } return -1;}

Cauta(v, function (x) { return x > 10; }); // 0

Cauta(v, function (x) { return x < 10; }); // 3

Page 20: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii imbricateDefiniţie

Funcţii definite în interiorul altor funcţii

Funcţii anonime

Funcţii non-anonime

Page 21: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

Funcţii imbricateExemple

function imbri(){ var mesaj = "salut"; function imbri2() { console.log(mesaj); }; imbri2(); };

imbri();// salut

function imbri(mesaj){ ( function () { console.log(mesaj); } ) (mesaj);};

imbri("test");// test

Page 22: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriDefiniţie

În engleză: closures

Funcţiile imbricate au acces la variabilele din funcţia părinte

Chiar şi după ce execuţia funcţiei părinte s-a terminat

Funcţia = (Funcţia imbricată, Variabile locale)

Variabilele nu sunt copiate ci este păstrată o referinţă

Page 23: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriExemple

function say(what) { var msg = "Mesaj: " + what; return function () { console.log(msg); };}

say('unu')(); // Mesaj: unusay('doi')();// Mesaj: doi

function say(what) { var ret = function () { console.log(msg); }; var msg = "Mesaj: " + what; return ret;}

say('unu')(); // Mesaj: unusay('doi')();// Mesaj: doi

Funcţia întoarsă are acces la variabila msg

Page 24: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriExemple

Acelaşi lucru este valabil şi pentru funcţii declanşate de evenimente

function sendRequest(url,callback,postData) { var req = createXMLHTTPObject(); if (!req) { return; } var method = (postData) ? "POST" : "GET"; req.open(method,url,true); req.setRequestHeader('User-Agent','XMLHTTP/1.0'); if (postData) { req.setRequestHeader('Content-type','application/x-www-form-urlencoded'); } req.onreadystatechange = function () { if (req.readyState != 4) return; if (req.status != 200 && req.status != 304) { alert('HTTP error ' + req.status); return; } callback(req); } if (req.readyState == 4) return; req.send(postData);}

Page 25: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriExemple

Mai multe funcţii imbricate au acces la aceeaşi închidere

function setup() { var num = 21; afiseaza = function () { console.log(num); } incrementeaza = function () { num++; }}

setup();afiseaza();// 21incrementeaza();afiseaza();// 22

setup();afiseaza();// 21

Page 26: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriGotchas

Ce este afisat?

function pregateste_functii(num) { var res = []; for (var i=0; i<num; i++) { res.push(function () { console.log(i); }); } return res;}

var funcs = pregateste_functii(4);for (var i=0; i<funcs.length; i++) { funcs[i]();}

Page 27: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriGotchas

Ce este afisat?

function pregateste_functii(num) { var res = []; for (var i=0; i<num; i++) { res.push(function () { console.log(i); }); } return res;}

var funcs = pregateste_functii(4);for (var i=0; i<funcs.length; i++) { funcs[i]();}

// 4// 4// 4// 4

Page 28: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriGotchas

this nu se comporta ca în alte limbaje

În acest caz this.loaded se referă la ajax_ob.loadedAclinkESM.prototype.loadTemplates = function () { if (this.individual_templates) { this.templates = [];

jQuery.ajax({ url: this.config.t_dir + 'anunt-container.ejs', processData: true, dataType: "text", success: function(data, status){ this.templates['anunt-container.ejs'] = data; this.loaded++; } }); this.toload++; ...

Page 29: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

ÎnchideriGotchas

Soluţia: copierea lui this în altă variabilă, tipic that sau self

AclinkESM.prototype.loadTemplates = function () { var that = this; if (this.individual_templates) { this.templates = [];

jQuery.ajax({ url: this.config.t_dir + 'anunt-container.ejs', processData: true, dataType: "text", success: function(data, status){ that.templates['anunt-container.ejs'] = data; that.loaded++; } }); this.toload++; ...

Page 30: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

CurryingDefiniţieNumit după Haskell Curry

Evaluarea parţială a funcţiilor

Modifică scope-ul la rulare

Matematic:

f (X x Y) -> Z

curry(f):X -> (Y -> Z)

Non matematic:console.log(aduna(2, 3));// 5var aduna4 = aduna(4);console.log(aduna4(10));// 14

Page 31: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

CurryingImplementare

function aduna(a) { return function (b) { return a + b; };}

var aduna4 = aduna(4);var aduna10 = aduna(10);

aduna4(5);// 9aduna10(5);// 15

Varianta simplă

Ideal ar fi să putem aplica procedeul la orice funcţie, fără să o modificăm

function aduna(a, b) { return a + b;}var aduna4 = aduna.curry(4);

Page 32: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

CurryingImplementareFunction.prototype.curry = function() { var fn = this, args = []; for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); return function() { for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); return fn.apply(window, args); }; };

function aduna(a, b) { return a + b;}

a = aduna.curry(5);b = aduna.curry(10);a(10); // 15b(10); // 20

Page 33: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

CurryingImplementare

Function.prototype.curry = function(scope) { var fn = this, args = []; var scope = scope || window; for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); return function() { for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); return fn.apply(scope, args); }; };

Uneori este utilă schimbarea scope-ului

bind din Prototype, dojo.lang.curry

Page 34: Concepte de programare functionala in Javascript

Programare funcțională în Javascript - Alexandru Badiu

CurryingExemple

function sayHello(msg) { console.log(msg + '\n You clicked on ' + this.id);}

var el1 = document.getElementById('element1');var el2 = document.getElementById('element2');

el1.addEventListener('click', sayHello.curry(el1, 'Hello'), false);el2.addEventListener('click', sayHello.curry(el2, 'Salut'), false);

function update(elem, data) { $(elem).html(data);}

$.get("foo.php", update.curry(window, 'elem1'));$.get("bar.php", update.curry(window, 'elem2'));

function update(data) { $(this).html(data);}

$.get("foo.php", update.curry($('elem1')));$.get("bar.php", update.curry($('elem2')));