lambdas functional examples c++ lambda

functional - Lambda Expression vs Functor en C++



std c++ (7)

1) Es trivial y tratar de compartirlo es más trabajo que beneficio.

2) Definir un functor simplemente agrega complejidad (debido a tener que hacer un montón de variables miembro y basura).

Si ninguna de esas cosas es cierta, entonces tal vez deberías pensar en definir un functor.

Editar: parece que necesitas un ejemplo de cuándo sería bueno usar una lambda sobre un functor. Aqui tienes:

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; }

Sin lambdas, tendrías que usar algo que de manera similar construye un functor en el lugar o escribir un objeto de funcionador externamente enlazable para algo que es molestamente trivial.

Por cierto, creo que wtf_error es una extensión.

Me pregunto dónde deberíamos usar la expresión lambda sobre el functor en C ++. Para mí, estas dos técnicas son básicamente las mismas, incluso el functor es más elegante y más limpio que el lambda . Por ejemplo, si quiero reutilizar mi predicado, tengo que copiar la parte lambda una y otra vez. Entonces, ¿cuándo realmente Lambda viene a colocar?


Como usted señaló, funciona mejor cuando necesita una sola vez y la sobrecarga de codificación de escribirla como una función no vale la pena.


Conceptualmente, la decisión de utilizar se basa en el mismo criterio que el uso de una variable nombrada frente a una expresión in situ o constante ...

size_t length = strlen(x) + sizeof(y) + z++ + strlen(''/0''); ... allocate(length); std::cout << length;

... aquí, la creación de una variable de longitud alienta al programa a considerar su corrección y significado de forma aislada de su uso posterior. El nombre del nombre transmite lo suficiente como para que pueda entenderse intuitivamente e independientemente de su valor inicial. Luego permite que el valor se use varias veces sin repetir la expresión (mientras que el manejo de z es diferente). Mientras aquí ...

allocate(strlen(x) + sizeof(y) + z++ + strlen(''/0''));

... el código total se reduce y el valor se localiza en el punto en que se necesita. Lo único que se puede "llevar adelante" de una lectura de esta línea son los efectos secundarios de la asignación y el incremento (z), pero no hay una variable local adicional con alcance o uso posterior que deba tenerse en cuenta. El programador tiene que hacer malabares mentalmente con menos estado mientras continúa su análisis del código.

La misma distinción se aplica a las funciones frente a las declaraciones en línea. Para los propósitos de responder a su pregunta, los funtores contra lambdas pueden verse como un caso particular de esta función versus una decisión preliminar.


Lambdas es básicamente azúcar sintáctica que implementa funtores (NB: los cierres no son simples). En C ++ 0x, puede usar la palabra clave auto para almacenar lambdas localmente, y std :: function le permitirá almacenar lambdas, o pasarlos alrededor de una manera segura de tipo.

Echa un vistazo al artículo de Wikipedia sobre C ++ 0x.


Pequeñas funciones que no se repiten.

La principal queja acerca de los funtores es que no están en el mismo lugar donde fueron utilizados. Por lo tanto, tenía que buscar y leer el functor fuera de contexto en el lugar en el que se estaba utilizando (incluso si solo se estaba utilizando en un lugar).

El otro problema era que el functor requería un cableado para obtener los parámetros en el objeto del functor. No es complejo, pero todo el código repetitivo básico. Y la placa de la caldera es susceptible a problemas de corte y pegado.

Lambda prueba y arregla ambos. Pero usaría funtores si la función se repite en múltiples lugares o es más pequeña que (no puedo imaginar un término apropiado, ya que será sensible al contexto) pequeña.


Una expresión lambda crea un functor sin nombre, es azúcar sintáctica.

Entonces lo usa principalmente si hace que su código se vea mejor. Eso generalmente ocurriría si (a) no vas a reutilizar el funtor, o (b) vas a reutilizarlo, pero de un código tan totalmente relacionado con el código actual que para compartirlo básicamente terminará creando my_favourite_two_line_functors.h , y los archivos dispares dependerán de ello.

Prácticamente las mismas condiciones bajo las cuales escribirías cualquier línea (s) de código, y no abstractas ese bloque de código en una función.

Dicho esto, con sentencias range-for en C ++ 0x, hay algunos lugares donde habría utilizado un functor antes, donde podría hacer que su código se vea mejor ahora para escribir el código como un cuerpo de bucle, no como un functor o un lambda.


lambda y functor tienen contexto. Functor es una clase y, por lo tanto, puede ser más complejo que una lambda. Una función no tiene contexto.

#include <iostream> #include <list> #include <vector> using namespace std; //Functions have no context, mod is always 3 bool myFunc(int n) { return n % 3 == 0; } //Functors have context, e.g. _v //Functors can be more complex, e.g. additional addNum(...) method class FunctorV { public: FunctorV(int num ) : _v{num} {} void addNum(int num) { _v.push_back(num); } bool operator() (int num) { for(int i : _v) { if( num % i == 0) return true; } return false; } private: vector<int> _v; }; void print(string prefix,list<int>& l) { cout << prefix << "l={ "; for(int i : l) cout << i << " "; cout << "}" << endl; } int main() { list<int> l={1,2,3,4,5,6,7,8,9}; print("initial for each test: ",l); cout << endl; //function, so no context. l.remove_if(myFunc); print("function mod 3: ",l); cout << endl; //nameless lambda, context is x l={1,2,3,4,5,6,7,8,9}; int x = 3; l.remove_if([x](int n){ return n % x == 0; }); print("lambda mod x=3: ",l); x = 4; l.remove_if([x](int n){ return n % x == 0; }); print("lambda mod x=4: ",l); cout << endl; //functor has context and can be more complex l={1,2,3,4,5,6,7,8,9}; FunctorV myFunctor(3); myFunctor.addNum(4); l.remove_if(myFunctor); print("functor mod v={3,4}: ",l); return 0; }

Salida:

initial for each test: l={ 1 2 3 4 5 6 7 8 9 } function mod 3: l={ 1 2 4 5 7 8 } lambda mod x=3: l={ 1 2 4 5 7 8 } lambda mod x=4: l={ 1 2 5 7 } functor mod v={3,4}: l={ 1 2 5 7 }