O que é um lambda e por que seria útil? [fechadas]

56

Até agora eu ouvi sobre:

  • Cálculo lambda
  • Programação Lambda
  • Expressões lambda
  • Funções Lambda

Tudo isso parece estar relacionado à programação funcional ...

Aparentemente, ele será integrado ao C ++ 1x, para que eu possa entender melhor agora:

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

Alguém pode definir brevemente o que são coisas lambdas e indicar onde pode ser útil?

jokoon
fonte
2
Observe que a terminologia historicamente vem do desejo de uma boa maneira de falar sobre a função representada por uma expressão. A função representada por x + 1 é então escrita lambda x. x + 1.
kasterma
De maneira lambda, uma função come outra função e / ou um valor de entrada, produz outra função. Isso continua até que uma função produz uma solução. Além disso, ovos de jacaré .
SD
É tudo grego para mim. Eu acho que vou ter um giroscópio, eu gosto de cordeiro, duh.

Respostas:

44
  • Cálculo lambda

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).

  • Programação Lambda

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 ith 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 ielemento th, precisaria de três argumentos ( ie 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 ipara 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 icomo 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 ielemento th, agora podemos criar um CompareByIthElementobjeto icomo 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 ielemento 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:

  1. Defina uma classe que tenha duas variáveis ​​de membro ( x1e x2) e uma operator()com os argumentos ( y1e y2) e o corpo bla.
  2. Crie uma instância da classe, definindo as variáveis ​​de membro x1e x2os valores das variáveis x1e x2atualmente 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á.

sepp2k
fonte
As funções anônimas são usadas com ponteiros de função? Se não, qual é a diferença?
jokoon
11
@jokoon: Não, funções anônimas não podem ser passadas como parâmetros para funções que recebem apenas ponteiros de função. No entanto, a maioria das funções que aceitam funções como argumentos são definidas usando modelos, para que possam ter qualquer tipo de objeto de função como argumento, não apenas como ponteiro de função. Ou seja, na maioria dos lugares em que você pode usar ponteiros de função ( std::sortpor exemplo), você poderá usar funções anônimas. No entanto, ao definir uma função que deve assumir uma função anônima como argumento, você precisa usar um modelo ou usar std::functioncomo o tipo de argumento.
sepp2k
assim um ponteiro de função não pode conter um lambda ...
jokoon
11
+1 Excelente explicação - eu também não consegui descobrir isso.
Michael K
2
Estou com Michael nisso. Isso é muito abrangente. +1de mim.
S10 /
18

Basicamente, funções lambda são funções que você cria "on the fly". No C ++ 1x, eles poderiam ser usados ​​para melhorar o suporte à programação funcional:

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

Isso resultará aproximadamente em um código semelhante a este:

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

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

Se você precisar some_functorapenas dessa chamada std::for_each(), essa função lambda terá várias vantagens sobre ela:

  • o que é feito no loop é especificado exatamente onde a função de loop é chamada
  • isso evita que você escreva um pouco do código da placa da caldeira
  • não há um functor em algum escopo de namespace que faça com que todos que olham o código se perguntem para que é necessário
sbi
fonte
7

Uma função lambda é outro nome para uma função anônima - essencialmente uma função sem nome.

Geralmente você usa isso em idiomas onde você precisará usar a função apenas uma vez. Por exemplo, em vez de

def add(a, b)
  return a+b

e depois passar essa função para outra função como essa

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

Com um lambda você faria simplesmente

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