it-swarm.it

Che cos'è una lambda e perché sarebbe utile?

Finora ho sentito parlare di:

  • Calcolo lambda
  • Programmazione lambda
  • Espressioni Lambda
  • Funzioni lambda

Che tutto sembra essere correlato alla programmazione funzionale ...

Apparentemente sarà integrato in C++ 1x, quindi potrei capire meglio ora:

http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions

Qualcuno può definire brevemente quali sono le cose lambdas e dare un dove può essere utile?

55
jokoon
  • Calcolo lambda

Il calcolo lambda è un modello di calcolo inventato dalla chiesa Alonzo negli anni '30. La sintassi e la semantica della maggior parte dei linguaggi di programmazione funzionale sono direttamente o indirettamente ispirati dal calcolo lambda.

Il calcolo lambda nella sua forma più semplice ha due operazioni: Astrazione (creazione di una funzione (anonima)) e applicazione (applicazione di una funzione). L'astrazione viene eseguita utilizzando l'operatore λ, dando il nome al calcolo lambda.

  • Espressioni Lambda
  • Funzioni lambda

Le funzioni anonime sono spesso chiamate "lambdas", "funzioni lambda" o "espressioni lambda" perché, come ho detto sopra, λ era il simbolo per creare funzioni anonime nel calcolo lambda (e la parola lambda è usata per creare funzioni anonime in molte lingue basate su LISP per lo stesso motivo).

  • Programmazione lambda

Questo non è un termine comunemente usato, ma presumo significhi programmare usando funzioni anonime o programmare usando funzioni di ordine superiore.


Un po 'più di informazioni su lambda in C++ 0x, la loro motivazione e il modo in cui si collegano ai puntatori di funzione (molto di questo è probabilmente una ripetizione di ciò che già conosci, ma spero che aiuti a spiegare la motivazione di lambda e come differiscono dai puntatori di funzione):

I puntatori a funzione, che già esistevano in C, sono abbastanza utili per es. passare una funzione di confronto a una funzione di ordinamento. Tuttavia ci sono limiti alla loro utilità:

Ad esempio, se si desidera ordinare un vettore di vettori in base all'elemento ith di ciascun vettore (dove i è un parametro di runtime), non è possibile risolverlo con un puntatore a funzione. Una funzione che confronta due vettori con il loro elemento ith, dovrebbe prendere tre argomenti (i e i due vettori), ma la funzione di ordinamento avrebbe bisogno di una funzione che prende due argomenti. Ciò di cui avremmo bisogno è un modo per fornire in qualche modo l'argomento i alla funzione prima di passarlo alla funzione di ordinamento, ma non possiamo farlo con semplici funzioni C.

Per risolvere questo, C++ ha introdotto il concetto di "oggetti funzione" o "functors". Un functor è fondamentalmente un oggetto che ha un metodo operator(). Ora possiamo definire una classe CompareByIthElement, che accetta l'argomento i come argomento del costruttore e quindi accetta i due vettori da confrontare come argomenti con il metodo operator(). Per ordinare un vettore di vettori in base all'elemento ith ora possiamo creare un oggetto CompareByIthElement con i come argomento e quindi passare quell'oggetto alla funzione di ordinamento.

Poiché gli oggetti funzione sono solo oggetti e non tecnicamente funzioni (anche se sono pensati per comportarsi come loro), non è possibile fare in modo che un puntatore a funzione punti a un oggetto funzione (si può ovviamente avere un puntatore a un oggetto funzione, ma esso avrebbe un tipo come CompareByIthElement* e quindi non sarebbe un puntatore a funzione).

La maggior parte delle funzioni nella libreria standard C++ che accettano funzioni come argomenti sono definite usando modelli in modo che funzionino con puntatori e oggetti funzione.

Ora a lambdas:

Definire un'intera classe da confrontare con l'elemento ith è un po 'prolisso se la userai solo una volta per ordinare un vettore. Anche nel caso in cui sia necessario solo un puntatore a funzione, definire una funzione con nome non è ottimale se viene utilizzata una sola volta perché a) inquina lo spazio dei nomi eb) la funzione di solito sarà molto piccola e non c'è davvero un buon motivo per astrarre la logica nella sua stessa funzione (a parte questo non è possibile avere puntatori di funzione senza definire una funzione).

Quindi per risolvere questo lambdas sono stati introdotti. Le lambda sono oggetti funzione, non puntatori di funzione. Se si utilizza un valore lambda letterale come il codice [x1, x2](y1,y2){bla} viene generato che sostanzialmente fa quanto segue:

  1. Definisci una classe con due variabili membro (x1 E x2) E una operator() con gli argomenti (y1 E y2) e il corpo bla.
  2. Crea un'istanza della classe, impostando le variabili membro x1 E x2 Sui valori delle variabili x1 E x2 Attualmente nell'ambito.

Quindi i lambda si comportano come oggetti funzione, tranne per il fatto che non è possibile accedere alla classe generata per implementare un lambda in alcun modo diverso dall'uso del lambda. Di conseguenza, qualsiasi funzione che accetta i funzioni come argomenti (che significa sostanzialmente qualsiasi funzione non C nella libreria standard), accetterà lambdas, ma qualsiasi funzione che accetta solo i puntatori a funzioni.

43
sepp2k

Fondamentalmente, le funzioni lambda sono funzioni create "al volo". In C++ 1x potrebbero essere utilizzati per migliorare il suo supporto per la programmazione funzionale:

std::for_each( begin, end, [](int i){std::cout << i << '\n';} );

Ciò comporterà approssimativamente un codice simile a questo:

struct some_functor {
  void operator()(int i) {std::cout << i << '\n';}
};

std::for_each( begin, end, some_functor() );

Se hai bisogno di some_functor Solo per questa chiamata a std::for_each(), allora quella funzione lambda presenta diversi vantaggi:

  • ciò che viene fatto nel loop viene specificato proprio dove viene chiamata la funzione di looping
  • ti allevia dalla scrittura del codice della piastra della caldaia
  • non c'è alcun funzione in giro in qualche ambito dello spazio dei nomi che induca tutti a guardare il codice chiedendosi a cosa serve
18
sbi

Una funzione lambda è un altro nome per una funzione anonima, essenzialmente una funzione senza nome.

Di solito lo usi in lingue in cui dovrai usare la funzione una sola volta. Ad esempio invece di

def add(a, b)
  return a+b

e quindi passare quella funzione in un'altra funzione in questo modo

reduce(add, [5,3,2])

Con una lambda faresti semplicemente

reduce(lambda x, y: a+b, [5,3,2])
7
Martin Konecny