O cálculo lambda é um modelo de computação inventado pela Igreja Alonzo nos anos 30. A sintaxe e a semântica da maioria das linguagens de programação funcionais são direta ou indiretamente inspiradas no cálculo lambda.
O cálculo lambda em sua forma mais básica possui duas operações: Abstração (criando uma função (anônima)) e aplicativo (aplique uma função). A abstração é realizada usando o operador λ, dando o nome ao cálculo lambda.
- Expressões lambda
- Funções Lambda
As funções anônimas são freqüentemente chamadas de "lambdas", "funções lambda" ou "expressões lambda" porque, como eu disse acima, λ era o símbolo para criar funções anônimas no cálculo lambda (e a palavra lambda
é usada para criar funções anônimas em muitos lisp idiomas baseados no mesmo motivo).
Este não é um termo comumente usado, mas presumo que isso signifique programar usando funções anônimas ou programar usando funções de ordem superior.
Um pouco mais de informações sobre lambdas em C ++ 0x, sua motivação e como elas se relacionam com ponteiros de função (muito disso é provavelmente uma repetição do que você já sabe, mas espero que ajude a explicar a motivação das lambdas e como elas diferem de ponteiros de função):
Ponteiros de função, que já existiam em C, são bastante úteis para, por exemplo, passar uma função de comparação para uma função de classificação. No entanto, existem limites para sua utilidade:
Por exemplo, se você deseja classificar um vetor de vetores pelo i
th elemento de cada vetor (onde i
é um parâmetro de tempo de execução), não é possível resolver isso com um ponteiro de função. Uma função que compara dois vetores pelo seu i
elemento th, precisaria de três argumentos ( i
e os dois vetores), mas a função de classificação precisaria de uma função que aceitasse dois argumentos. O que precisamos é de uma maneira de fornecer o argumento i
para a função antes de passá-lo para a função de classificação, mas não podemos fazer isso com funções C simples.
Para resolver isso, o C ++ introduziu o conceito de "objetos de função" ou "functors". Um functor é basicamente um objeto que possui um operator()
método. Agora podemos definir uma classe CompareByIthElement
, que aceita o argumento i
como argumento construtor e, em seguida, leva os dois vetores a serem comparados como argumentos ao operator()
método. Para classificar um vetor de vetores pelo i
elemento th, agora podemos criar um CompareByIthElement
objeto i
como argumento e depois passar esse objeto para a função de classificação.
Como os objetos de função são apenas objetos e não tecnicamente funções (mesmo que eles se comportem como eles), não é possível fazer um ponteiro de função apontar para um objeto de função (é claro que você pode ter um ponteiro para um objeto de função, mas ele teria um tipo como CompareByIthElement*
e, portanto, não seria um ponteiro de função).
A maioria das funções na biblioteca padrão C ++, que aceitam funções como argumentos, são definidas usando modelos, para que funcionem com ponteiros de função e objetos de função.
Agora para lambdas:
Definir uma classe inteira para comparar pelo i
elemento th é um pouco detalhado, se você for usá-la apenas uma vez para classificar um vetor. Mesmo no caso em que você só precisa de um ponteiro de função, definir uma função nomeada fica abaixo do ideal se for usada apenas uma vez porque a) polui o espaço para nome eb) a função geralmente é muito pequena e não existe realmente um bom motivo para abstrair a lógica em sua própria função (exceto que você não pode ter ponteiros de função sem definir uma função).
Então, para corrigir isso, lambdas foram introduzidas. Lambdas são objetos de função, não indicadores de função. Se você usar um literal lambda como [x1, x2](y1,y2){bla}
código é gerado, basicamente faz o seguinte:
- Defina uma classe que tenha duas variáveis de membro (
x1
e x2
) e uma operator()
com os argumentos ( y1
e y2
) e o corpo bla
.
- Crie uma instância da classe, definindo as variáveis de membro
x1
e x2
os valores das variáveis x1
e x2
atualmente no escopo.
Portanto, os lambdas se comportam como objetos de função, exceto que você não pode acessar a classe que é gerada para implementar um lambda de outra maneira que não seja o uso do lambda. Conseqüentemente, qualquer função que aceite functors como argumentos (basicamente significando qualquer função não-C na biblioteca padrão) aceitará lambdas, mas qualquer função que aceite apenas ponteiros de função não aceitará.