Czym jest ta „Lambda”, o której wszyscy mówią? Wydaje się, że wielu ludzi to uwielbia, ale wszystko, co mogę z tego wyciągnąć, to po prostu sposób na upchanie wielu linii kodu w jednym wyrażeniu.
Czy ktoś może mnie oświecić na temat jego prawdziwej wartości?
Odpowiedzi:
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 () {}; // very simple
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
for
iwhile
pę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++) { // do what something useful with array[i] }
używając
forEach
obiektów tablicy of, staje się:array.forEach(function (element, index) { // do something useful with element // element is the equivalent of array[i] from above });
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ładfilter
: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);
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
Runnable
interfejs.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]) { // expensive operations to get a user. Ajax for example 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]) { // expensive operations to get a user. Ajax for example photos[name] = photo_from_ajax; } return photos[name]; };
Jest tam wyraźnie jakiś wzór, więc odejmijmy go. Użyjmy zapamiętywania .
/** * @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 });
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
users
iphotos
.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ół
store
parametru. W ten sposób mam dostęp do tego parametru nawet po tym, jakmemoize
funkcja zwróciła swój wynik (lambdę).źródło
Termin „lambda” jest używany w odniesieniu do funkcji anonimowej, zwykle zamknięcia . Są przydatne, ponieważ pozwalają pisać funkcje, które używają innych funkcji bez niepotrzebnego nadużywania kodu. Na przykład w Rubim:
Spowoduje to utworzenie tablicy zawierającej liczby parzyste z przedziału od 1 do 100. Nie musimy pisać jawnej pętli - metoda select przyjmuje funkcję, której używa do testowania wartości, więc potrzebujemy tylko naszej niestandardowej logiki. To pozwala nam w znacznym stopniu dostosować metodę praktycznie bez wysiłku i kosztów. Zasadniczo możemy składać funkcje z mniejszych funkcji.
To tylko prosty przykład tego, co mogą zrobić. Możliwość przekazywania funkcji jako danych jest naprawdę potężna, a programiści języka funkcjonalnego rutynowo robią z nią naprawdę niesamowite rzeczy.
źródło
„Lambda” może po prostu za mało. Spójrz na rachunek Lambda . Jest to przydatne w programowaniu funkcjonalnym.
A programowanie funkcjonalne to kolejny paradygmat programowania (podobny do proceduralnego lub obiektowego).
źródło
Lambdy w .NET są często określane jako „cukier syntaktyczny”. Nie wpływają bezpośrednio na funkcjonalność, ale ułatwiają korzystanie z języka.
Kiedy zrozumiesz moc ich używania, jestem pewien, że zauważysz, że będziesz pisać mniej kodu w porównaniu do starego stylu przy użyciu metod delegowanych / anonimowych.
źródło
Dr Dobbs Journal ma przydatny artykuł wprowadzający wyrażenia lambda (w kontekście C ++, ale myślę, że możesz zastosować te zasady do dowolnego języka).
Jak czytamy w artykule: „Wyrażenie lambda to bardzo zwarte wyrażenie, które nie wymaga oddzielnej definicji klasy / funkcji”.
A więc na przykładach aukcji 1 i 2 z DDJ zamiast pisać:
Co wymaga oddzielnej definicji klasy, takiej jak:
Korzystając z biblioteki Boost lambda, może to wyglądać:
Co utrzymuje definicję w linii.
Artykuł wyjaśniono również kilka innych zastosowań wyrażeń lambda.
Myślę, że kluczową kwestią w artykule DDJ jest „Zazwyczaj wyrażenia lambda są używane, gdy w miejscu wywołania potrzebne są małe i niezbyt złożone funkcje. Gdyby funkcja była nietrywialna, nie chciałbyś wyrażenia lambda, ale normalną funkcję lub obiekt funkcji. "
źródło
Jeśli kiedykolwiek pracowałeś z funkcjami / metodami, które używają wskaźników funkcji, delegatów, strategii lub obsługi wzorca / zdarzenia obserwatora i pomyślałeś sobie „Piszę całą tę funkcję tylko po to, aby jej użyć tylko raz - aby przekazać ją do tej metody Chciałbym móc po prostu napisać to w miejscu, zamiast zaśmiecać mój kod ”- tam właśnie możesz użyć funkcji Lambda. Języki obsługujące tę konstrukcję również zwykle w dużym stopniu wykorzystują koncepcję przekazywania funkcji jako parametrów, szczególnie w odniesieniu do pracy z listami (funkcje pierwszej klasy i funkcje wyższego rzędu). Jest to szczególnie prawdziwe w przypadku języków funkcjonalnych, które polegają na składaniu funkcji, a nie modyfikacji pamięci do obliczeń. W niektórych przypadkach (w językach takich jak Python)
źródło
„lambda” qua słowo to terminologia z czasów, gdy osoby z informatyki z równym prawdopodobieństwem zdobywały wykształcenie matematyczne lub logiczne, co stopień naukowy informatyki. Niektórzy z nich wymyślili paradygmat zwany „programowaniem funkcjonalnym”, zupełnie inny niż imperatyw i również dość potężny. AFAIK czyli środowisko, w którym termin ten wszedł w życie.
Matematycy i logicy mają skłonność do używania dziwnych słów.
„lambda” brzmi naprawdę ezoterycznie - jakby było bardzo dziwną i wyjątkową rzeczą. Naprawdę, jeśli piszesz JavaScript dla aplikacji przeglądarkowej i używasz idiomu "var foo = function () {...}", to od dawna używasz funkcji lambda.
źródło
Wyrażenie lambda to prosta forma funkcji. Chodzi o to, że coś z formularza po lewej stronie (odpowiednik parametrów) staje się czymś z formy po prawej stronie (odpowiednik ciała).
na przykład w cis:
jest lambdą do kwadratu wartości. Coś w formie
staje się czymś w rodzaju formy
źródło
„Wyrażenie lambda to anonimowa funkcja, która może zawierać wyrażenia i instrukcje i może być używana do tworzenia delegatów lub typów drzew wyrażeń.
Wszystkie wyrażenia lambda używają operatora lambda =>, który jest odczytywany jako „idzie do”. Lewa strona operatora lambda określa parametry wejściowe (jeśli istnieją), a prawa strona zawiera wyrażenie lub blok instrukcji. Wyrażenie lambda x => x * x jest odczytywane „x idzie do x razy x”.
z MSDN
źródło
Pełne wyjaśnienie wyrażeń Lambda można znaleźć również w Wikipedii . (Przewiń w dół do rachunku Lambda i języków programowania ). Wyrażenia lambda nie są takie nowe i nie są tylko częścią C #, ale czymś, co zostało wprowadzone do przetwarzania danych prawie 80 lat temu! Wyrażenia lambda są podstawą programowania funkcjonalnego.
Czy to wartość? Biorąc pod uwagę, że jest dość stary, powiedziałbym: bardzo cenny dla każdego, kto wykonuje obliczenia.
źródło
Jeśli interesujesz się Javą, wiele słyszałeś o lambdach lub domknięciach w ciągu ostatnich kilku miesięcy, ponieważ były różne propozycje dodania tej funkcji do Java 7. Jednak wydaje mi się, że komisja porzuciła tę funkcję. Jedna z propozycji pochodzi od Neala Gaftera i została szczegółowo wyjaśniona tutaj: javac.info . Pomogło mi to zrozumieć przypadki użycia i zalety (zwłaszcza w porównaniu z klasami wewnętrznymi)
źródło
Wszystko, co musisz wiedzieć (o C # lambdach) na początek, znajdziesz tutaj:
Wyrażenia lambda
źródło
W przypadku lambd Java może to być dobry punkt wyjścia:
http://rodrigouchoa.wordpress.com/2014/09/10/java-8-lambda-expressions-tutorial/
źródło
Tak, jest to po prostu sposób na upchanie wielu wierszy kodu w jednym wyrażeniu. Ale będąc tak efektywnym wkuwaniem, umożliwia nowe sposoby strukturyzacji programu.
Często można by uniknąć pisania delegatów lub wywołań zwrotnych i powrócić do stylu proceduralnego po prostu dlatego, że deklarowanie nowych funkcji lub klas dla pojedynczego wyrażenia jest zbyt pracochłonne.
Wyrażenia lambda sprawiają, że warto używać wywołań zwrotnych nawet w przypadku najmniejszych zadań, co może uczynić kod bardziej przejrzystym. Może nie.
źródło