domenica 22 novembre 2009
mercoledì 4 novembre 2009
Rails: usare template grafici con Rails
In this screencast, I show you how to easily add a layout with built-in menus to your existing Rails application.
martedì 3 novembre 2009
Functional.js - High order function - Parte 3 : Function composition
Nella programmazione funzionale per function composition s'intende la combinazione di funzioni semplici all'interno di una funzione più complessa.
Questo composizione, permette di creare una funzione che è il risultato di una concatenazione di funzioni.
Unica condizione è che queste funzioni accettino come parametro di input e di return un unico parametro.
Functional.js mette a disposizione 2 funzioni per la function composition: sequence e compose.
Vediamo un esempio pratico, scrivendo:
Functional.install()
var fnSequence=sequence('+1','+2','+3','*100');
console.log("sequence -> (100+1+2+3)*100=",fnSequence(100));
var fnCompose=compose('+1','+2','+3','*100');
console.log("compose -> (100*100)+3+2+1=",fnCompose(100));
otteniamo come risultato:
sequence -> (100+1+2+3)*100= 10600
compose -> (100*100)+3+2+1= 10006
come vedete sequence crea una concatenazione dal primo all'ultimo parametro-funzione, mentre compose dall'ultimo al primo parametro-funzione.
Ogni String Lambda è una funziona unaria, che accetta un unico parametro di input e lo ritorna trasformato in qualcos'altro.
Il principio è molto simile alla pipe della shell di linux:
tail -f | grep error
Come sempre è possibile usare le HOF che lavorano sulle liste, come la map, per usare la function composition:
scriviamo questo codice
var lista=[1,2,3,4,5,6,7,8,9,10];
var ret=map(sequence('+1','+2','+3','*100'),list);
console.log("map(sequence('+1','+2','+3','*100'),list)=",ret);
var ret=map(compose('+1','+2','+3','*100'),list);
console.log("map(compose('+1','+2','+3','*100'),list)=",ret);
e otteniamo come risultato:
map(sequence('+1','+2','+3','*100'),list)= [700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600]
map(compose('+1','+2','+3','*100'),list)= [106, 206, 306, 406, 506, 606, 706, 806, 906, 1006]
Nel prossimo Post su Functional.js chiuderemo il discorso introduttivo sulle HOF con l'introduzione dei concetti di currying e partial. Dopo di che vedremo qualche
esempio pratico di programmazione funzionale da usare nella routine di tutti i giorni con javascript.
Questo composizione, permette di creare una funzione che è il risultato di una concatenazione di funzioni.
Unica condizione è che queste funzioni accettino come parametro di input e di return un unico parametro.
Functional.js mette a disposizione 2 funzioni per la function composition: sequence e compose.
Vediamo un esempio pratico, scrivendo:
Functional.install()
var fnSequence=sequence('+1','+2','+3','*100');
console.log("sequence -> (100+1+2+3)*100=",fnSequence(100));
var fnCompose=compose('+1','+2','+3','*100');
console.log("compose -> (100*100)+3+2+1=",fnCompose(100));
otteniamo come risultato:
sequence -> (100+1+2+3)*100= 10600
compose -> (100*100)+3+2+1= 10006
come vedete sequence crea una concatenazione dal primo all'ultimo parametro-funzione, mentre compose dall'ultimo al primo parametro-funzione.
Ogni String Lambda è una funziona unaria, che accetta un unico parametro di input e lo ritorna trasformato in qualcos'altro.
Il principio è molto simile alla pipe della shell di linux:
tail -f | grep error
Come sempre è possibile usare le HOF che lavorano sulle liste, come la map, per usare la function composition:
scriviamo questo codice
var lista=[1,2,3,4,5,6,7,8,9,10];
var ret=map(sequence('+1','+2','+3','*100'),list);
console.log("map(sequence('+1','+2','+3','*100'),list)=",ret);
var ret=map(compose('+1','+2','+3','*100'),list);
console.log("map(compose('+1','+2','+3','*100'),list)=",ret);
e otteniamo come risultato:
map(sequence('+1','+2','+3','*100'),list)= [700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600]
map(compose('+1','+2','+3','*100'),list)= [106, 206, 306, 406, 506, 606, 706, 806, 906, 1006]
Nel prossimo Post su Functional.js chiuderemo il discorso introduttivo sulle HOF con l'introduzione dei concetti di currying e partial. Dopo di che vedremo qualche
esempio pratico di programmazione funzionale da usare nella routine di tutti i giorni con javascript.
Functional.js - High order function - Parte 2 : Funzioni condizionali
And Or e Not sono tre HOF che accettano come parametri delle funzioni, che vengono utilizzate per generare una nuova funzione basate sulle condizioni delle funzioni di input.
Vediamo qualche esempio
Functional.install()
var ret=and('>5','<10')(8);
console.log(">5 and <10",ret);
var ret=or('>5','<10')(8);
console.log(">5 or <10",ret);
var ret=not('>5')(8);
console.log("not >5",ret);
e otterremo come risultato:
>5 and <10 true
>5 or <10 true
not >5 false
Possiamo usare queste HOF condizionali anche con la funzione filter applicata a una lista:
Functional.install()
var list=[1,2,3,4,5,6,7,8,9,10];
var ret=filter(and('>4','<9'),list);
console.log(">4 and <9",ret);
var ret=filter(not(and('>4','<9')),list);
console.log("not (>4 and <9)",ret);
e otteniamo:
>4 and <9 [5, 6, 7, 8]
not (>4 and <9) [1, 2, 3, 4, 9, 10]
Vediamo qualche esempio
Functional.install()
var ret=and('>5','<10')(8);
console.log(">5 and <10",ret);
var ret=or('>5','<10')(8);
console.log(">5 or <10",ret);
var ret=not('>5')(8);
console.log("not >5",ret);
e otterremo come risultato:
>5 and <10 true
>5 or <10 true
not >5 false
Possiamo usare queste HOF condizionali anche con la funzione filter applicata a una lista:
Functional.install()
var list=[1,2,3,4,5,6,7,8,9,10];
var ret=filter(and('>4','<9'),list);
console.log(">4 and <9",ret);
var ret=filter(not(and('>4','<9')),list);
console.log("not (>4 and <9)",ret);
e otteniamo:
>4 and <9 [5, 6, 7, 8]
not (>4 and <9) [1, 2, 3, 4, 9, 10]
Etichette:
condizioni,
functional programming,
functional.js,
high order function
lunedì 2 novembre 2009
Functional.js - High order function - Parte 1
In questo secondo post su Functional.js vediamo l'introduzione alle High Order Function (HOF).
Le HOF nella programmazione funzionale (FP), sono funzioni che possono manipolare altre funzione, accettarle come parametri, creare nuove funzioni, o trasformarle in altre funzioni.
Un esempio classico che viene usato nella FP, con l'uso delle closure, è l'accumulator:
Se provate a eseguire questo codice:
var generateAccumulator=function(start) {
return function(n) {
start=start+n;
console.log(start);
return start;
}
};
fnAcc=generateAccumulator(10);
fnAcc(1);
fnAcc(2);
fnAcc(3);
otterrete come risultato:
11
13
16
Come vedete grazie alle closure è possibile mantenere lo stato delle variabili interne della funzione (in questo caso la variabile start inizializzata come parametro).
Functional.js ci mette a disposizione una serie di funzioni molto usate nella FP. In questo articolo approfondiamo quelle che lavorano su una lista e che in parte sono state mutuate dal LISP:
map, select, some, every e reduce.
Partiamo con un esempio pratico, per poi entrare in dettaglio su quello che abbiamo ottenuto.
Intanto dovete scaricarvi la libreria functional.js che trovate a questo indirizzo http://github.com/osteele/functional-javascript, inserirla dentro una pagina html.
Poi caricate la pagina dentro firefox, aprite firebug e dentro la finestra di console scrivete questo codice:
Functional.install();
Functional.install();
var lst=[1,2,3,4,5,6,7,8,9,10];
var ret=map('+100',lst);
console.log("map",ret);
var ret=filter('>5',lst);
console.log("log",ret);
var ret=some('>5',lst);
console.log("some",ret);
var ret=every('>5',lst);
console.log("every",ret);
var ret=reduce('x+y',0,lst);
console.log("reduce",ret);
e otterremo questo come output:
map [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
log [6, 7, 8, 9, 10]
some true
every false
reduce 55
Come vedere queste funzioni accetta 2 parametri (al di fuori di reduce) una lambda String (vedi questo articolo come introduzione) e una lista:
map -> trasforma una lista in un'altra lista (fa un mapping)
filter -> applica un filtro a una lista e ne ritorna una filtrata
every -> torna true se tutti gli elementi della lista soddisfano la condizione della funzione
some -> torna true se almeno un elemento della lista soddisfa la condizione della funzione
reduce -> accetta tre parametri (una funzione di trasformazione, un valore o oggetto iniziale e la lista), applica una riduzione della lista
usando la funzione di trasformazione, fino a ritornare un unico oggetto (è l'equivalente di inject in smalltalk o ruby, e di fold).
Con queste 5 funzioni abbiamo quasi tutto per poter manipolare con tranquillità strutture dati basate su liste.
Ovviamente possiamo usare anche strutture dati più complesse come liste di oggetti:
Functional.install();
var persons=[
{name:'paolo',surname:'rossi',age:35},
{name:'mario', surname:'bianchi', age:55 },
{name:'luigi',surname:'neri',age:22}
];
var ret=map('.name',persons);
console.log("lista dei nomi",ret)
var ret=filter('.age < 40',persons);
console.log("persone minori di 40 anni di età",ret);
var ret=every('.age > 10',persons);
console.log('tutti hanno più di 10 anni?',persons);
var ret=some('.age > 30',persons);
console.log('almeno una persona ha più di 30 anni?',persons);
Vi ricordo che queste funzioni possono ricevere come parametri funzione sia string lambda che normali funzioni javascript
Le HOF nella programmazione funzionale (FP), sono funzioni che possono manipolare altre funzione, accettarle come parametri, creare nuove funzioni, o trasformarle in altre funzioni.
Un esempio classico che viene usato nella FP, con l'uso delle closure, è l'accumulator:
Se provate a eseguire questo codice:
var generateAccumulator=function(start) {
return function(n) {
start=start+n;
console.log(start);
return start;
}
};
fnAcc=generateAccumulator(10);
fnAcc(1);
fnAcc(2);
fnAcc(3);
otterrete come risultato:
11
13
16
Come vedete grazie alle closure è possibile mantenere lo stato delle variabili interne della funzione (in questo caso la variabile start inizializzata come parametro).
Functional.js ci mette a disposizione una serie di funzioni molto usate nella FP. In questo articolo approfondiamo quelle che lavorano su una lista e che in parte sono state mutuate dal LISP:
map, select, some, every e reduce.
Partiamo con un esempio pratico, per poi entrare in dettaglio su quello che abbiamo ottenuto.
Intanto dovete scaricarvi la libreria functional.js che trovate a questo indirizzo http://github.com/osteele/functional-javascript, inserirla dentro una pagina html.
Poi caricate la pagina dentro firefox, aprite firebug e dentro la finestra di console scrivete questo codice:
Functional.install();
Functional.install();
var lst=[1,2,3,4,5,6,7,8,9,10];
var ret=map('+100',lst);
console.log("map",ret);
var ret=filter('>5',lst);
console.log("log",ret);
var ret=some('>5',lst);
console.log("some",ret);
var ret=every('>5',lst);
console.log("every",ret);
var ret=reduce('x+y',0,lst);
console.log("reduce",ret);
e otterremo questo come output:
map [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
log [6, 7, 8, 9, 10]
some true
every false
reduce 55
Come vedere queste funzioni accetta 2 parametri (al di fuori di reduce) una lambda String (vedi questo articolo come introduzione) e una lista:
map -> trasforma una lista in un'altra lista (fa un mapping)
filter -> applica un filtro a una lista e ne ritorna una filtrata
every -> torna true se tutti gli elementi della lista soddisfano la condizione della funzione
some -> torna true se almeno un elemento della lista soddisfa la condizione della funzione
reduce -> accetta tre parametri (una funzione di trasformazione, un valore o oggetto iniziale e la lista), applica una riduzione della lista
usando la funzione di trasformazione, fino a ritornare un unico oggetto (è l'equivalente di inject in smalltalk o ruby, e di fold).
Con queste 5 funzioni abbiamo quasi tutto per poter manipolare con tranquillità strutture dati basate su liste.
Ovviamente possiamo usare anche strutture dati più complesse come liste di oggetti:
Functional.install();
var persons=[
{name:'paolo',surname:'rossi',age:35},
{name:'mario', surname:'bianchi', age:55 },
{name:'luigi',surname:'neri',age:22}
];
var ret=map('.name',persons);
console.log("lista dei nomi",ret)
var ret=filter('.age < 40',persons);
console.log("persone minori di 40 anni di età",ret);
var ret=every('.age > 10',persons);
console.log('tutti hanno più di 10 anni?',persons);
var ret=some('.age > 30',persons);
console.log('almeno una persona ha più di 30 anni?',persons);
Vi ricordo che queste funzioni possono ricevere come parametri funzione sia string lambda che normali funzioni javascript
Etichette:
every,
filter,
functional programming,
functional.js,
high order function,
map,
reduce,
some
domenica 1 novembre 2009
dojo e jQuery: divergenze su map
Dojo e jQuery sono 2 libreria che uso spesso e che adoro molto, soprattutto perchè hanno 2 approcci molto differenti sul come scrivere applicazioni web.
In particolare l'uso della funzione map differisce un pò tra le 2 librerie, soprattutto in 2 punti:
1) utilizzo del this:
jQuery usa il this come riferimento degli oggetti che devono esssere mappati mentre Dojo passa il riferimento come parametro.
in jQuery infatti scriveremo cosi:
$([1,2,3,4,5,6,7,8,9,10]).map(function() { return this +5 });
in Dojo invece:
dojo.map([1,2,3,4,5,6,7,8,9,10],function(el) { return el + 5});
2) return null:
in jQuery se ritorniamo un null l'oggetto su cui si sta mappando viene tolto dalla lista generata dalla funzione map:
$([1,2,3,4,5,6,7,8,9,10].map(function() { return this>5 ? this : null });
ci ritornera [6,7,8,9,10]
in Dojo invece:
dojo.map([1,2,3,4,5,6,7,8,9,10],function(el) { return el>5 ? this : null });
ritornera [1,2,3,4,5,null,null,null,null,null]
Questo perchè la map in jQuery può essere usata come funzione di filter oltre che di mapping.
in dojo per avere un filtro invece dovremo usare la funzione dojo.filter:
dojo.filter([1,2,3,4,5,6,7,8,9,10],function(el) { return el>6 });
In particolare l'uso della funzione map differisce un pò tra le 2 librerie, soprattutto in 2 punti:
1) utilizzo del this:
jQuery usa il this come riferimento degli oggetti che devono esssere mappati mentre Dojo passa il riferimento come parametro.
in jQuery infatti scriveremo cosi:
$([1,2,3,4,5,6,7,8,9,10]).map(function() { return this +5 });
in Dojo invece:
dojo.map([1,2,3,4,5,6,7,8,9,10],function(el) { return el + 5});
2) return null:
in jQuery se ritorniamo un null l'oggetto su cui si sta mappando viene tolto dalla lista generata dalla funzione map:
$([1,2,3,4,5,6,7,8,9,10].map(function() { return this>5 ? this : null });
ci ritornera [6,7,8,9,10]
in Dojo invece:
dojo.map([1,2,3,4,5,6,7,8,9,10],function(el) { return el>5 ? this : null });
ritornera [1,2,3,4,5,null,null,null,null,null]
Questo perchè la map in jQuery può essere usata come funzione di filter oltre che di mapping.
in dojo per avere un filtro invece dovremo usare la funzione dojo.filter:
dojo.filter([1,2,3,4,5,6,7,8,9,10],function(el) { return el>6 });
Iscriviti a:
Post (Atom)