View Full Version : [JS] Funzione "partial application"
legolas93
30-12-2011, 18:35
Ciao ragazzi. Sto continuando nella lettura del mio libro di Javascript solo che sono arrivato ad una cosa a mio modo di vedere assurda :D
Dato
function asArray(quasiArray, start) {
var result = [];
for (var i = (start || 0); i < quasiArray.length; i++)
result.push(quasiArray[i]);
return result;
}
function partial(func) {
var fixedArgs = asArray(arguments, 1);
return function(){
return func.apply(null, fixedArgs.concat(asArray(arguments)));
};
}
function map(func, array) {
var result = [];
forEach(array, function (element) {
result.push(func(element));
});
return result;
}
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
var op = {
"+": function(a, b){return a + b;},
"==": function(a, b){return a == b;},
"===": function(a, b){return a === b;},
"!": function(a){return !a;}
/* and so on */
}
Leggo "Now equals(10) can be written as partial(op["=="], 10)."
:confused:
Ma partial non prevede una singola funzione come argomento. :confused: Cosa ci fa li il "10"?
Grazie ragazzi.
EDIT:
per testarlo ho usato un comando tipo:
alert(map(partial(op["=="], 10),[10,2,3]).join(" "));
e cavolo..:muro: funziona.. :doh: ..io non capisco nella definizione della funzione dove entra in gioco il 10..
Gimli[2BV!2B]
30-12-2011, 20:45
Riguardo la tua prima perplessità, cioè l'argomento di troppo, devi sapere che in Javascript è possibile invocare una funzione con un numero qualsiasi di parametri.
Se sono inferiori a quelli definiti i mancanti risultano undefined e sono paragonabili a parametri con valori di default, con il lato negativo che la cosa deve essere ben prevista e gestita correttamente all'interno della funzione, altrimenti l'esecuzione prosegue tranquillamente fino a che un undefined la fa andare in direzioni indesiderate.
function test(a, b)
{
alert(b);
}
function testDef(a, b)
{
if( ! b ) b = 0 ;
alert(b);
}
test(1);
testDef(1);
Se invece sono in numero superiore verranno normalmente ignorati, ma sono tranquillamente accessibili tramite lo pseudo array arguments, permettendo una veloce implementazione di funzioni variadiche.function test()
{
var somma = 0;
for (var i = 0; i < arguments.length; i++)
somma += arguments[i];
alert(arguments.length + ': sommatoria -> ' + somma);
}
test();
test(1,2);
test(1,2,10);A questo unisci il metodo apply: questo invoca la funzione a cui appartiene nello scope passato come primo parametro e con tutti i valori contenuti nell'array passato come secondo argomento utilizzati come parametri.
Tenendo presente queste cose il quadro inizia a comporsi.
Resta comunque un Picasso, però si inizia ad apprezzare la follia della cosa...
P.S. puoi togliere di mezzo la funzione map, alleggerendo un po' il ragionamento, invocando direttamente il risultato di partialalert( partial(op["=="], 10)(10) ) ;
alert( partial(op["=="], 10)(9) ) ;
var op = {
"+": function(a, b){return a + b;},
"==": function(a, b){return a == b;},
"===": function(a, b){return a === b;},
"!": function(a){return !a;}
/* and so on */
}
function (){
var fixedArgs = new Array(1) ; fixedArgs[0] = 10 ; /* partial(op["=="], 10)(9) */
var func = op["=="] ; /* partial(op["=="], 10)(9) */
return func.apply(null, fixedArgs.concat(asArray(arguments)));
}(9) /* partial(op["=="], 10)(9) */
//Risultato false
legolas93
31-12-2011, 10:10
I tuoi esempi gli ho capiti benebene :)
Ora torniamo a:
alert(map(partial(op["=="], 10),[10,2,3]).join(" "));
Semplificato a:
map(partial(op["=="], 10),[10,2,3]
Se ce la fai seguimi e dimmi se è giusto il ragionamento.
Quando io chiamo
partial(op["=="], 10
fixedArgs = [10] Vero? :)
e mi ritorna una funzione di Uguaglianza applicata alla concatenazione tra fixedArgs e arguments. Penso di essere ancora nel giusto, no?.
Ma quest'ultimo arguments agli argomenti di quale funzione si riferisce? A quella anonima all'interno di partial?
Io sono propenso per la seconda.
E come faccio a riempire i parametri della funzione anonima?
Con questo:
result.push(func(element)); //del map
Sono ancora nel giusto? :)
Gimli[2BV!2B]
31-12-2011, 13:23
Quando io chiamo
partial(op["=="], 10
fixedArgs = [10] Vero? :) Sì
e mi ritorna una funzione di Uguaglianza applicata alla concatenazione tra fixedArgs e arguments. Penso di essere ancora nel giusto, no?.Perfetto
Ma quest'ultimo arguments agli argomenti di quale funzione si riferisce? A quella anonima all'interno di partial?Esatto
E come faccio a riempire i parametri della funzione anonima?
Con questo:
result.push(func(element)); //del map
Sono ancora nel giusto? :)Mmh, qui non credo tu sia ancora sulla strada giusta. result contiene i risultati di tutte le esecuzioni della funzione recuperata dall'array associativo op, il confronto di uguaglianza.
La funzione anonima viene invocata più volte, ogni volta con il successivo elemento dell'array [10,2,3] in forEach.
map invoca forEach, di cui eredita lo scope (var result = []; ed il fondamentale parametro func)
forEach esegue la funzione anonima passata come parametro action
action viene eseguita nel ciclo che scorre array salvando nel result di map
cercando a ritroso l'origine di array si arriva a [10,2,3] dell'invocazionealert(map(partial(op["=="], 10),[10,2,3]).join(" "));
Ok, ho ricontrollato e non mi pare di aver scritto boiate, certo che 'sti esempi son simpatici :asd:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.