functional programming in java script

Post on 10-May-2015

1.278 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

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 &raquo;'); } else { jQuery(this).html('&laquo; 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')));

?Alexandru Badiui@voidberg.org

http://voidberg.org

top related