Il lambda calcolo è un modello di calcolo inventato da Alonzo Church negli anni '30. La sintassi e la semantica della maggior parte dei linguaggi di programmazione funzionale sono direttamente o indirettamente ispirati al calcolo lambda.
Il calcolo lambda nella sua forma base ha due operazioni: Astrazione (creando una funzione (anonima)) e applicazione (applica una funzione). L'astrazione viene eseguita usando l'operatore λ, dando il nome al calcolo lambda.
- Espressioni Lambda
- Funzioni lambda
Le funzioni anonime sono spesso chiamate "lambda", "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).
Questo non è un termine comunemente usato, ma presumo che significhi programmare usando funzioni anonime o programmando usando funzioni di ordine superiore.
Un po 'più di informazioni su lambdas in C ++ 0x, la loro motivazione e il loro rapporto con i puntatori di funzione (molto probabilmente è una ripetizione di ciò che già sai, ma spero che aiuti a spiegare la motivazione di lambdas e in che modo differiscono dai puntatori di funzione):
I puntatori di funzione, che già esistevano in C, sono piuttosto utili ad es. passare una funzione di confronto a una funzione di ordinamento. Tuttavia ci sono dei limiti alla loro utilità:
Ad esempio, se si desidera ordinare un vettore di vettori mediante l'elemento i
th 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 i
th, dovrebbe prendere tre argomenti ( i
e i due vettori), ma la funzione di ordinamento avrebbe bisogno di una funzione che prendesse due argomenti. Quello 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 problema, C ++ ha introdotto il concetto di "oggetti funzionali" o "funtori". Un functor è fondamentalmente un oggetto che ha un metodo operator()
. Ora possiamo definire una classe CompareByIthElement
, che accetta l'argomento i
come argomento costruttore e quindi accetta i due vettori da confrontare come argomenti al metodo operator()
. Per ordinare un vettore di vettori dall'elemento i
th possiamo ora 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 funzioni tecnicamente (anche se hanno lo scopo di comportarsi come loro), non è possibile creare una funzione puntatore a un oggetto funzione (si può ovviamente avere un puntatore a un oggetto funzione , ma avrebbe un tipo come CompareByIthElement*
e quindi non dovrebbe essere un puntatore a funzione).
La maggior parte delle funzioni nella libreria standard C ++ che assumono funzioni come argomenti vengono definite utilizzando i modelli in modo che possano funzionare con i puntatori di funzione e gli oggetti funzione.
Now to lambdas:
Definire un'intera classe da confrontare con l'elemento i
th è un po 'prolisso se lo utilizzerai solo una volta per ordinare un vettore. Anche nel caso in cui hai solo bisogno di un puntatore a funzione, la definizione di una funzione con nome è sub-ottimale se viene utilizzata una sola volta a causa del fatto che inquina lo spazio dei nomi eb) la funzione di solito sarà molto piccola e non c'è una buona ragione per astrarre la logica in una sua funzione (oltre a quella che non puoi avere puntatori di funzione senza definire una funzione).
Quindi per risolvere questo problema sono stati introdotti i lambda. Lambdas sono oggetti funzione, non indicatori di funzione. Se si utilizza un letterale lambda come [x1, x2](y1,y2){bla}
viene generato il codice che fondamentalmente fa quanto segue:
- Definisci una classe che ha due variabili membro (
x1
e x2
) e una operator()
con gli argomenti ( y1
e y2
) e il corpo bla
.
- Crea un'istanza della classe, impostando le variabili membro
x1
e x2
sui valori delle variabili x1
e x2
attualmente in ambito.
Quindi lambda si comporta come gli oggetti funzione, tranne per il fatto che non è possibile accedere alla classe generata per implementare un lambda in un modo diverso dall'uso del lambda. Di conseguenza, qualsiasi funzione che accetta i funtori come argomenti (che fondamentalmente significa qualsiasi funzione non-C nella libreria standard), accetterà lambda, ma non funzionerà alcuna funzione che accetta solo i puntatori di funzione.