Funkcje bez nazwy
Mówiąc najprościej, lambda to funkcja bez nazwy lub funkcja anonimowa. Mały fragment kodu wykonywalnego, który można przekazać tak, jakby był zmienną. W JavaScript:
function () {};
Zobaczmy teraz niektóre zastosowania tych lambd.
Abstrakcyjny kod schematyczny
Lambdy mogą być użyte do wyodrębnienia kodu standardowego. Na przykład pętle. Jesteśmy przyzwyczajeni do pisania fori whilepętli przez cały dzień. Ale to jest kod, którego się nie pisze. Moglibyśmy wyodrębnić kod wewnątrz pętli, najważniejszą część pętli i usunąć resztę:
for (var i=0; i<array.length; i++) {
}
używając forEachobiektów tablicy of, staje się:
array.forEach(function (element, index) {
});
Powyższa abstrakcja może nie być przydatna, ale istnieją inne funkcje wyższego rzędu, takie jak forEach, które wykonują znacznie bardziej przydatne zadania. Na przykład filter:
var numbers = [1, 2, 3, 4];
var even = [];
for (var i=0; i<numbers.length; i++) {
if (numbers[i] % 2 === 0) {
even.push(numbers[i]);
}
}
alert(even);
even = [1, 2, 3, 4].filter(function (number) {
return number % 2 === 0;
});
alert(even);
Opóźnienie wykonania kodu
W niektórych środowiskach, w których pojęcie zdarzenia jest dostępne, moglibyśmy użyć lambd, aby odpowiedzieć na zdarzenia, które mogą się wydarzyć w pewnym momencie.
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
Można to zrobić na inne sposoby, ale są one raczej rozwlekłe. Na przykład w Javie jest Runnableinterfejs.
Fabryki funkcji
Do tego momentu używaliśmy tylko lambd głównie ze względu na ich możliwości związane z cukrem syntaktycznym. Ale są sytuacje, w których lambdy mogą być znacznie bardziej przydatne. Na przykład możemy mieć funkcje, które zwracają lambdy. Powiedzmy, że mamy funkcję, dla której chcemy, aby jej zwracane wartości były buforowane.
var users = [];
var getUser = function (name) {
if (! users[name]) {
users[name] = user_from_ajax;
}
return users[name];
};
Później możemy zauważyć, że mamy podobną funkcję:
var photos = [];
var getPhoto = function (name) {
if (! photo[name]) {
photos[name] = photo_from_ajax;
}
return photos[name];
};
Jest tam wyraźnie jakiś wzór, więc odejmijmy go. Użyjmy zapamiętywania .
var memoize = function (store, lambda) {
return function (name) {
if (! store[name]) {
store[name] = lambda(name);
}
return store[name];
};
};
var getUsers = memoize([], function (name) {
});
var getPhotos = memoize([], function (name) {
});
Jak widać, używając lambd, byliśmy w stanie wyodrębnić logikę buforowania / zapamiętywania. Gdyby w drugim przykładzie istniały jakieś obejścia, uważam, że ten konkretny problem jest trudny do rozwiązania za pomocą innych technik. Udało nam się wyodrębnić ważny kod standardowy w jednym miejscu. Nie wspominając o tym, że pozbyliśmy się zmiennych globalnych usersi photos.
Patrząc na Twój profil, widzę, że jesteś głównie użytkownikiem Pythona. W przypadku powyższego wzorca Python ma koncepcję dekoratorów. W sieci jest wiele przykładów dekoratorów zapamiętywania . Jedyną różnicą jest to, że w Pythonie najprawdopodobniej masz nazwaną zagnieżdżoną funkcję wewnątrz tej funkcji dekoratora. Powodem jest to, że Python obsługuje tylko wyrażenia lambda z jednym wyrażeniem. Ale koncepcja jest taka sama.
Jako przykład użycia lambda w Pythonie. Powyższy kod, w którym odfiltrowaliśmy liczby parzyste, można przedstawić w Pythonie w następujący sposób:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
W każdym razie lambdy nie są tak potężne bez zamknięć. Zamknięcia są tym, co sprawia, że koncepcja lambd jest tak potężna. W moim przykładzie zapamiętywania użyłem domknięć, aby utworzyć zamknięcie wokół storeparametru. W ten sposób mam dostęp do tego parametru nawet po tym, jak memoizefunkcja zwróciła swój wynik (lambdę).