Funziona senza nome
In poche parole, un lambda è una funzione senza nome o una funzione anonima. Un piccolo pezzo di codice eseguibile, che può essere passato in giro come se fosse una variabile. In JavaScript:
function () {}; // very simple
Vediamo ora alcuni usi per questi lambda.
Astrazione del codice boilerplate
Lambdas può essere utilizzato per astrarre il codice boilerplate. Ad esempio i loop. Siamo abituati a scrivere for
e fare while
loop tutto il giorno. Ma questo è un codice che non si scrive. Potremmo estrarre il codice all'interno del ciclo, la parte più importante del ciclo, e astrarre il resto:
for (var i=0; i<array.length; i++) {
// do what something useful with array[i]
}
utilizzando gli forEach
oggetti array of, diventa:
array.forEach(function (element, index) {
// do something useful with element
// element is the equivalent of array[i] from above
});
L'astrazione di cui sopra potrebbe non essere così utile, ma ci sono altre funzioni di ordine superiore, come forEach
, che eseguono compiti molto più utili. Ad esempio filter
:
var numbers = [1, 2, 3, 4];
var even = [];
// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
if (numbers[i] % 2 === 0) {
even.push(numbers[i]);
}
}
alert(even);
// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
return number % 2 === 0;
});
alert(even);
Ritardo di esecuzione del codice
In alcuni ambienti, in cui è disponibile il concetto di evento, potremmo usare lambda per rispondere a eventi che possono accadere in un determinato momento.
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
Questo avrebbe potuto essere fatto in altri modi, ma quelli sono piuttosto prolissi. Ad esempio, in Java c'è l' Runnable
interfaccia.
Fabbriche di funzioni
Fino a questo punto, abbiamo utilizzato principalmente lambda per le sue capacità di zucchero sintattico. Ma ci sono situazioni in cui i lambda possono essere molto più utili. Ad esempio, potremmo avere funzioni che restituiscono lambda. Supponiamo di avere una funzione che vogliamo che i suoi valori di ritorno vengano memorizzati nella cache.
var users = [];
var getUser = function (name) {
if (! users[name]) {
// expensive operations to get a user. Ajax for example
users[name] = user_from_ajax;
}
return users[name];
};
In seguito, potremmo notare che abbiamo una funzione simile:
var photos = [];
var getPhoto = function (name) {
if (! photo[name]) {
// expensive operations to get a user. Ajax for example
photos[name] = photo_from_ajax;
}
return photos[name];
};
C'è chiaramente uno schema lì dentro, quindi astraggiamolo. Usiamo la memoizzazione .
/**
* @param {Array} store Data structure in which we cache lambda's return values
* @param {Function} lambda
* @return {Function} A function that caches the result of calling the lambda param
*/
var memoize = function (store, lambda) {
// return a new lambda
return function (name) {
if (! store[name]) {
// Execute the lambda and cache the result
store[name] = lambda(name);
}
return store[name];
};
};
var getUsers = memoize([], function (name) {
// expensive operations to get a user. Ajax for example
});
var getPhotos = memoize([], function (name) {
// expensive operations to get a photo. Ajax for example
});
Come puoi vedere, usando lambda, siamo stati in grado di astrarre la logica di caching / memoization. Se per l'altro esempio ci fossero delle soluzioni alternative, credo che questo particolare problema sia difficilmente risolvibile utilizzando altre tecniche. Siamo riusciti a estrarre alcuni importanti codici boilerplate in un unico posto. Per non parlare del fatto che ci siamo sbarazzati delle variabili globali users
e photos
.
Guardando il tuo profilo vedo che sei principalmente un utente Python. Per il modello sopra, Python ha il concetto di decoratori. Ci sono molti esempi in rete per i decoratori di memoization . L'unica differenza è che in Python molto probabilmente hai una funzione annidata con nome all'interno di quella funzione decoratore. Il motivo è che Python supporta solo espressioni lambda a singola espressione. Ma il concetto è lo stesso.
Come esempio di utilizzo lambda di Python. Il codice sopra in cui abbiamo filtrato i numeri pari può essere rappresentato in Python in questo modo:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
Ad ogni modo, i lambda non sono così potenti senza chiusure. Le chiusure sono ciò che rende il concetto di lambda così potente. Nel mio esempio di memoizzazione ho usato delle chiusure per creare una chiusura attorno al store
parametro. In questo modo, ho accesso a quel parametro anche dopo che la memoize
funzione ha restituito il suo risultato (un lambda).