functional programming in java script

49

Upload: thinkphp

Post on 10-May-2015

1.277 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Functional programming in java script

Programare funcţională în JavascriptAlexandru Badiu

Page 2: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Logică

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

Page 8: Functional programming in java script

Programare funcțională în Javascript - Alexandru Badiu

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

(alert “Hello World!”)

Page 9: Functional programming in java script

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Limbaje ezoterice

HAICAN HAS STDIO?VISIBLE "HAI WORLD!"KTHXBYE

Page 10: Functional programming in java script

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?HTML

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

Page 11: Functional programming in java script

Programare funcțională în Javascript - Alexandru Badiu

Ce este programarea funcţională?Javascript

Page 12: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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: Functional programming in java script

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')));