concepte de programare functionala in javascript
DESCRIPTION
Prezentare de la Wurbe 14.TRANSCRIPT
Programare funcţională în JavascriptAlexandru Badiu
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
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
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
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;}
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!" ); }}
Programare funcțională în Javascript - Alexandru Badiu
Ce este programarea funcţională?Logică
?- write(”Hello World!”), nl.
Programare funcțională în Javascript - Alexandru Badiu
Ce este programarea funcţională?Funcţională
(alert “Hello World!”)
Programare funcțională în Javascript - Alexandru Badiu
Ce este programarea funcţională?Limbaje ezoterice
HAICAN HAS STDIO?VISIBLE "HAI WORLD!"KTHXBYE
Programare funcțională în Javascript - Alexandru Badiu
Ce este programarea funcţională?HTML
<p>HTML nu este un limbaj de programare.</p>
Programare funcțională în Javascript - Alexandru Badiu
Ce este programarea funcţională?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
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
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
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
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
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
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 »'); } else { jQuery(this).html('« Mai putine'); } return false;});
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
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
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
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ţă
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
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);}
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
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]();}
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
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++; ...
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++; ...
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
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);
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
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
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')));
Programare funcțională în Javascript - Alexandru Badiu
Resursehttp://www.joelonsoftware.com/items/2006/08/01.html
http://osteele.com/archives/2007/07/functional-javascript
http://invisibleblocks.wordpress.com/2007/02/23/functional-programming-in-javascript-and-ruby/
?Alexandru [email protected]
http://voidberg.org