Zastanawiam się, gdzie powinniśmy użyć wyrażenia lambda w stosunku do funktora w C++. Dla mnie te dwie techniki są w zasadzie takie same, nawet funktor jest bardziej elegancki i czystszy niż lambda. Na przykład, jeśli chcę ponownie użyć mojego predykatu, muszę wielokrotnie kopiować część lambda. Kiedy więc lambda naprawdę wchodzi na miejsce?Lambda Expression vs Functor w C++
Odpowiedz
1) To banalne, a próba udostępnienia go to więcej pracy niż korzyści.
2) Definiowanie funktora po prostu dodaje złożoności (z powodu konieczności zrobienia paczki zmiennych członków i bzdur).
Jeśli żadna z tych rzeczy nie jest prawdziwa, może powinieneś pomyśleć o zdefiniowaniu funktora.
Edytuj: wydaje się, że potrzebujesz przykładu, kiedy byłoby miło użyć lambda na funktorze. Proszę bardzo:
typedef std::vector< std::pair<int,std::string> > whatsit_t;
int find_it(std::string value, whatsit_t const& stuff)
{
auto fit = std::find_if(stuff.begin(), stuff.end(), [value](whatsit_t::value_type const& vt) -> bool { return vt.second == value; });
if (fit == stuff.end()) throw std::wtf_error();
return fit->first;
}
Bez lambdas trzeba by użyć czegoś, podobnie konstruuje funktora na miejscu lub napisać zewnętrznie skorelowane obiekt funktora za coś, co jest irytująco trywialne.
BTW, myślę, że może wtf_error jest rozszerzeniem.
Nie zapominaj, że zaśmiecasz przestrzeń nazw klasami funktora. –
@Paul Nathan: Zostało to rozwiązane przez anonimowe przestrzenie nazw. –
Roberts: dzięki za bardzo ładny przykład użycia Lamda. – Chan
Jak zauważyłeś, działa najlepiej, gdy potrzebujesz jednorazowej operacji, a narzut związany z kodowaniem zapisywania jej jako funkcji nie jest tego wart.
dzięki za szybką odpowiedź. Ale nie rozumiem, jaka była motywacja do wymyślania 'lamda', ponieważ uważam, że trudniej ją odczytać i nie można jej użyć ponownie. Nie ma również nazwy, więc odczyt kodu wymaga znacznie więcej czasu. – Chan
@Chan: Herb Sutter był jednym z najbardziej zagorzałych zwolenników lambd. Opowiedział o nich: http://herbsutter.com/2010/10/30/pdc-languages-panel-andshortened-lambdas-talk/. Nie obserwowałem ich osobiście, ale bez wątpienia powiedzą ci, do czego * on * sądzi, że są dla nich dobre, i podam przykłady, kiedy ich użyje. –
@Steve Jessop: dzięki za link. Obejrzę to. – Chan
Wyrażenie lambda tworzy bezimienny funktor, to syntaktyczny cukier.
Używasz go głównie wtedy, gdy poprawia twój kod. Zdarza się to zazwyczaj, gdy (a) nie zamierzasz ponownie użyć funktora, lub (b) zamierzasz go ponownie użyć, ale z kodu tak całkowicie niezwiązanego z bieżącym kodem, że w celu jego udostępnienia zasadniczo w końcu tworzy się my_favourite_two_line_functors.h
i zależą od niego różne pliki.
Niemal takie same warunki, w których można wpisać dowolną linię kodu, a nie abstrahować, że kod blokuje się w funkcję.
To powiedziawszy, w przypadku instrukcji range-for w C++ 0x, jest kilka miejsc, w których używałbyś funktora, zanim dobrze by teraz wyglądał, aby Twój kod wyglądał lepiej teraz, aby zapisać kod jako ciało pętli, a nie funktor lub lambda.
Niewielkie funkcje, które nie są powtarzane.
Głównym narzekaniem na funktory jest to, że nie znajdują się w tym samym miejscu, w którym zostały użyte. Musiałeś więc znaleźć i odczytać funktor z kontekstu do miejsca, w którym był on używany (nawet jeśli jest używany tylko w jednym miejscu).
Innym problemem było to, że funktor wymagał okablowania, aby uzyskać parametry obiektu funktora. Nie jest to skomplikowany, ale cały podstawowy kod na płycie głównej. Płyta kotła jest podatna na przecięcia i wklejenia.
Lambda wypróbuj i napraw oba. Ale użyłbym funktorów, jeśli funkcja jest powtarzana w wielu miejscach lub jest większa niż (nie można wymyślić odpowiedniego terminu, ponieważ będzie to kontekstowa) mała.
Lambdas to w zasadzie właśnie cukier syntaktyczny, który implementuje funktory (Uwaga: zamknięcia nie są proste.) W C++ 0x możesz użyć słowa kluczowego auto do lokalnego zapisywania lambdas, a funkcja std :: umożliwi zapisywanie lambdas lub przekazywanie ich w bezpieczny sposób.
Zapoznaj się z Wikipedia article on C++0x.
koncepcyjnym, którego decyzja w użyciu jest napędzany przez tego samego kryterium, jak za pomocą zmiennej o nazwie kontra wyrażenie lub stała w miejscu ...
size_t length = strlen(x) + sizeof(y) + z++ + strlen('\0');
...
allocate(length);
std::cout << length;
. ..tutaj, tworzenie zmiennej długości zachęca program do rozważenia jego poprawności i znaczenia w oderwaniu od jego późniejszego użycia. Nazwa ma nadzieję, że przekazuje się na tyle, że można ją zrozumieć intuicyjnie i niezależnie od jej początkowej wartości. Następnie pozwala na użycie wartości kilkakrotnie bez powtarzania wyrażenia (przy jednoczesnym zachowaniu innej wartości). Podczas gdy tutaj ...
allocate(strlen(x) + sizeof(y) + z++ + strlen('\0'));
... całkowity kod jest zmniejszany, a wartość jest zlokalizowana w miejscu, w którym jest potrzebna. Jedyną rzeczą do "przeniesienia naprzód" z odczytu tej linii są skutki uboczne przydziału i przyrostu (z), ale nie ma dodatkowej zmiennej lokalnej z zakresem lub późniejszym zastosowaniem do rozważenia. Programista musi mentalnie żonglować mniej stanu, kontynuując analizę kodu.
To samo rozróżnienie dotyczy instrukcji funkcji a instrukcji śródliniowych. Aby odpowiedzieć na twoje pytanie, funktory versus lambdy mogą być postrzegane tylko jako szczególny przypadek tej funkcji w stosunku do podejmowania decyzji.
- 1. C# Pass Lambda Expression as Method Parametr
- 2. MethodInvoke delegate lub lambda expression
- 3. Lambda Expression za pomocą foreach Klauzulę
- 4. Jak przekazać wartość rvalue C++ functor do przechwytywania lambda?
- 5. Java Lambda Expression i logowania
- 6. C#: Expression
- 7. Grupa przez hrabiego i Lambda Expression
- 8. Uzyskaj wartość z ASP.NET MVC Lambda Expression
- 9. Groovy odpowiednik dla Java 8 Lambda Expression
- 10. Jak wypełnić HashMap za pomocą Lambda Expression
- 11. Uzyskaj niestandardowe atrybuty z Lambda Property Expression
- 12. Funkcja lokalna vs Lambda C# 7.0
- 13. oddzielając dwie wartości kolumn w LINQ Lambda Expression
- 14. Scala odpowiednik C# 's Expression API
- 15. C++ 11 lambda w decltype
- 16. Aplikacje WPF: Visual Studio vs. Expression Blend
- 17. C++ statyczne wydajność lambda
- 18. Lambda-Over-Lambda w C++ 14
- 19. Expression jest zawsze prawdziwe w C#
- 20. Tworzenie (a, a) Functor
- 21. lambda w C++ 03
- 22. Scalanie strumieni map za pomocą Java 8 Lambda Expression
- 23. Jak uzyskać średnią długość słowa za pomocą Lambda Expression
- 24. Brak instancji Cats Functor [Future]
- 25. C++ Boost Multi Index, modyfikuj wymaga Functor, nie kompilujesz
- 26. Przełącznik C# w wyrażeniu lambda
- 27. Jaki jest cel (<$) w klasie Functor?
- 28. Przekształcanie drzewa stanu C++ Phoenix Expression
- 29. C# XPath help - Expression nie działa
- 30. Niezgodność typu podczas pisania instancji Functor dla
BTW, nie wiem, że wstawiłbym "lambda" jako kod. To nie jest słowo kluczowe lub typ w C++. Jest coś takiego jak "wyrażenie lambda", ale "lambda" nie jest czymś, co zobaczyłbyś w kodzie, chyba że korzystałeś z biblioteki lambda boost lub faktycznie miałeś coś, co nazywa się tym w twoim własnym kodzie. –
@ Noah Roberts: dzięki za wskazanie tego. Edytowane! Chciałem podkreślić to słowo. – Chan