Pergunta

Para uma pessoa sem formação em ciência da computação, o que é um lambda no mundo da Ciência da Computação?

Foi útil?

Solução

Lambda vem do Cálculo Lambda e refere-se a funções anônimas em programação.

Por que isso é legal?Ele permite que você escreva funções de descarte rápido sem nomeá-las.Ele também fornece uma ótima maneira de escrever encerramentos.Com esse poder você pode fazer coisas assim.

Pitão

def adder(x):
    return lambda y: x + y
add5 = adder(5)
add5(1)
6

Como você pode ver no trecho de Python, o somador de função recebe um argumento x e retorna uma função anônima, ou lambda, que recebe outro argumento y.Essa função anônima permite criar funções a partir de funções.Este é um exemplo simples, mas deve transmitir o poder que lambdas e fechamentos têm.

Exemplos em outros idiomas

Perl 5

sub adder {
    my ($x) = @_;
    return sub {
        my ($y) = @_;
        $x + $y
    }
}

my $add5 = adder(5);
print &$add5(1) == 6 ? "ok\n" : "not ok\n";

JavaScript

var adder = function (x) {
    return function (y) {
        return x + y;
    };
};
add5 = adder(5);
add5(1) == 6

JavaScript (ES6)

const adder = x => y => x + y;
add5 = adder(5);
add5(1) == 6

Esquema

(define adder
    (lambda (x)
        (lambda (y)
           (+ x y))))
(define add5
    (adder 5))
(add5 1)
6

C# 3.5 ou superior

Func<int, Func<int, int>> adder = 
    (int x) => (int y) => x + y; // `int` declarations optional
Func<int, int> add5 = adder(5);
var add6 = adder(6); // Using implicit typing
Debug.Assert(add5(1) == 6);
Debug.Assert(add6(-1) == 5);

// Closure example
int yEnclosed = 1;
Func<int, int> addWithClosure = 
    (x) => x + yEnclosed;
Debug.Assert(addWithClosure(2) == 3);

Rápido

func adder(x: Int) -> (Int) -> Int{
   return { y in x + y }
}
let add5 = adder(5)
add5(1)
6

PHP

$a = 1;
$b = 2;

$lambda = function () use (&$a, &$b) {
    echo $a + $b;
};

echo $lambda();

Haskell

(\x y -> x + y) 

Java ver esta postagem

// The following is an example of Predicate : 
// a functional interface that takes an argument 
// and returns a boolean primitive type.

Predicate<Integer> pred = x -> x % 2 == 0; // Tests if the parameter is even.
boolean result = pred.test(4); // true

Lua

adder = function(x)
    return function(y)
        return x + y
    end
end
add5 = adder(5)
add5(1) == 6        -- true

Kotlin

val pred = { x: Int -> x % 2 == 0 }
val result = pred(4) // true

Rubi

Ruby é um pouco diferente porque você não pode chamar um lambda usando exatamente a mesma sintaxe que chama uma função, mas ainda possui lambdas.

def adder(x)
  lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6

Ruby sendo Ruby, existe uma abreviação para lambdas, então você pode definir adder Por aqui:

def adder(x)
  -> y { x + y }
end

Outras dicas

Um lambda é um tipo de função definida em linha.Junto com um lambda, você geralmente também tem algum tipo de variável que pode conter uma referência a uma função, lambda ou outra.

Por exemplo, aqui está um trecho de código C# que não usa lambda:

public Int32 Add(Int32 a, Int32 b)
{
    return a + b;
}

public Int32 Sub(Int32 a, Int32 b)
{
    return a - b;
}

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, Add);
    Calculator(10, 23, Sub);
}

Isso chama Calculator, passando não apenas dois números, mas qual método chamar dentro de Calculator para obter os resultados do cálculo.

No C# 2.0 temos métodos anônimos, que encurtam o código acima para:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a + b;
    });
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a - b;
    });
}

E então, no C# 3.0, obtivemos lambdas, o que torna o código ainda mais curto:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, (a, b) => a + b);
    Calculator(10, 23, (a, b) => a - b);
}

Isso se refere a cálculo lambda, que é um sistema formal que possui apenas expressões lambda, que representam uma função que recebe uma função como único argumento e retorna uma função.Todas as funções no cálculo lambda são desse tipo, ou seja, λ : λ → λ.

Lisp usou o conceito lambda para nomear seus literais de função anônima.Este lambda representa uma função que recebe dois argumentos, x e y, e retorna seu produto:

(lambda (x y) (* x y)) 

Pode ser aplicado em linha assim (avaliado para 50):

((lambda (x y) (* x y)) 5 10)

O nome "lambda" é apenas um artefato histórico.Estamos falando apenas de uma expressão cujo valor é uma função.

Um exemplo simples (usando Scala para a próxima linha) é:

args.foreach(arg => println(arg))

onde o argumento para o foreach método é uma expressão para uma função anônima.A linha acima é mais ou menos o mesmo que escrever algo assim (código não muito real, mas você vai entender):

void printThat(Object that) {
  println(that)
}
...
args.foreach(printThat)

exceto que você não precisa se preocupar com:

  1. Declarar a função em outro lugar (e ter que procurá-la quando você revisitar o código posteriormente).
  2. Nomear algo que você usa apenas uma vez.

Depois que você estiver acostumado a funcionar com valores, ficar sem eles parece tão bobo quanto ser obrigado a nomear todas as expressões, como:

int tempVar = 2 * a + b
...
println(tempVar)

em vez de apenas escrever a expressão onde você precisa:

println(2 * a + b)

A notação exata varia de idioma para idioma;O grego nem sempre é obrigatório!;-)

O cálculo lambda é uma teoria matemática consistente de substituição.Na matemática escolar vemos, por exemplo x+y=5 emparelhado com x−y=1.Junto com as formas de manipular equações individuais, também é possível reunir as informações dessas duas, desde que as substituições de equações cruzadas sejam feitas de forma lógica.O cálculo lambda codifica a maneira correta de fazer essas substituições.

Dado que y = x−1 é um rearranjo válido da segunda equação, isto: λ y = x−1 significa uma função que substitui os símbolos x−1 para o símbolo y.Agora imagine aplicar λ y para cada termo da primeira equação.Se um termo for y em seguida, faça a substituição;caso contrário, não faça nada.Se você fizer isso no papel, verá como aplicar isso λ y tornará a primeira equação solucionável.

Essa é uma resposta sem qualquer ciência da computação ou programação.

O exemplo de programação mais simples que consigo pensar vem de http://en.wikipedia.org/wiki/Joy_(programming_linguagem)#How_it_works:

Aqui está como a função quadrada pode ser definida em uma linguagem de programação imperativa (c):

int square(int x)
{
    return x * x;
}

A variável x é um parâmetro formal que é substituído pelo valor real a ser quadrado quando a função é chamada.Em uma linguagem funcional (esquema), a mesma função seria definida:

(define square
  (lambda (x) 
    (* x x)))

Isso é diferente de várias maneiras, mas ainda usa o parâmetro formal X da mesma maneira.


Adicionado: http://imgur.com/a/XBHub

lambda

Um pouco simplificado:uma função lambda é aquela que pode ser passada para outras funções e sua lógica acessada.

Em C#, a sintaxe lambda geralmente é compilada para métodos simples da mesma maneira que delegados anônimos, mas também pode ser dividida e sua lógica lida.

Por exemplo (em C#3):

LinqToSqlContext.Where( 
    row => row.FieldName > 15 );

LinqToSql pode ler essa função (x > 15) e convertê-la no SQL real para executar usando árvores de expressão.

A afirmação acima fica:

select ... from [tablename] 
where [FieldName] > 15      --this line was 'read' from the lambda function

Isso é diferente dos métodos normais ou delegados anônimos (que na verdade são apenas mágica do compilador) porque eles não podem ser ler.

Nem todos os métodos em C# que usam sintaxe lambda podem ser compilados em árvores de expressão (ou seja,funções lambda reais).Por exemplo:

LinqToSqlContext.Where( 
    row => SomeComplexCheck( row.FieldName ) );

Agora a árvore de expressão não pode ser lida - SomeComplexCheck não pode ser decomposto.A instrução SQL será executada sem o where e cada linha dos dados será submetida SomeComplexCheck.

As funções Lambda não devem ser confundidas com métodos anônimos.Por exemplo:

LinqToSqlContext.Where( 
    delegate ( DataRow row ) { 
        return row.FieldName > 15; 
    } );

Isso também tem uma função 'inline', mas desta vez é apenas mágica do compilador - o compilador C# dividirá isso em um novo método de instância com um nome gerado automaticamente.

Métodos anônimos não podem ser lidos e, portanto, a lógica não pode ser traduzida como acontece com funções lambda.

Gosto da explicação dos Lambdas neste artigo: A evolução do LINQ e seu impacto no design do C#.Fez muito sentido para mim, pois mostra um mundo real para Lambdas e o desenvolve como um exemplo prático.

Sua explicação rápida:Lambdas são uma forma de tratar código (funções) como dados.

Um exemplo de lambda em Ruby é o seguinte:

hello = lambda do
    puts('Hello')
    puts('I am inside a proc')
end

hello.call

Irá gerar a seguinte saída:

Hello
I am inside a proc

@Brian Eu uso lambdas o tempo todo em C#, em operadores LINQ e não LINQ.Exemplo:

string[] GetCustomerNames(IEnumerable<Customer> customers)
 { return customers.Select(c=>c.Name);
 }

Antes do C#, eu usava funções anônimas em JavaScript para retornos de chamada para funções AJAX, antes mesmo de o termo Ajax ser cunhado:

getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/});

O interessante da sintaxe lambda do C#, porém, é que por si só seu tipo não pode ser inferido (ou seja, você não pode digitar var foo = (x,y) => x * y), mas dependendo do tipo que eles são atribuídos, eles serão compilados como delegados ou árvores de sintaxe abstratas que representam a expressão (que é como os mapeadores de objetos LINQ fazem sua mágica "integrada à linguagem").

Lambdas em LISP também podem ser passados ​​para um operador de cotação e depois percorridos como uma lista de listas.Algumas macros poderosas são feitas dessa maneira.

A pergunta é formalmente respondida de maneira ampla, então não tentarei acrescentar mais nada sobre isso.

De forma muito simples, informal palavras para alguém que sabe muito pouco ou nada de matemática ou programação, eu explicaria isso como uma pequena "máquina" ou "caixa" que recebe alguma entrada, faz algum trabalho e produz alguma saída, não tem um nome específico, mas sabemos onde é e apenas por esse conhecimento, nós o usamos.

Praticamente falando, para uma pessoa que sabe o que é uma função, eu diria que é uma função que não tem nome, geralmente colocada em um ponto na memória que pode ser usada apenas fazendo referência a essa memória (geralmente através do uso de uma variável - se eles ouviram sobre o conceito de ponteiros de função, eu os usaria como um conceito semelhante) - esta resposta cobre o básico (sem menção a fechamentos, etc.), mas pode-se entender facilmente.

Você pode pensar nisso como uma função anônima - aqui estão mais algumas informações: Wikipedia - Função anônima

Só porque não consigo ver um exemplo de C++ 11 aqui, irei em frente e postarei este belo exemplo de aqui.Depois de pesquisar, é o exemplo específico de linguagem mais claro que consegui encontrar.

Olá, Lambdas, versão 1

template<typename F>

void Eval( const F& f ) {
        f();
}
void foo() {
        Eval( []{ printf("Hello, Lambdas\n"); } );
}

Olá, Lambdas, versão 2:

void bar() {
    auto f = []{ printf("Hello, Lambdas\n"); };
    f();
}

Tenho dificuldade em entender as expressões lambda porque trabalho no Visual FoxPro, que tem substituição de macro e as funções ExecScript{} e Evaluate(), que parecem servir praticamente ao mesmo propósito.

? Calculator(10, 23, "a + b")
? Calculator(10, 23, "a - b");

FUNCTION Calculator(a, b, op)
RETURN Evaluate(op)

Um benefício definitivo do uso de lambdas formais é (presumo) a verificação em tempo de compilação:O Fox não saberá se você digitou a string de texto acima até tentar executá-la.

Isso também é útil para código baseado em dados:você pode armazenar rotinas inteiras em campos de memorando no banco de dados e apenas avaliá-las em tempo de execução.Isso permite ajustar parte do aplicativo sem realmente ter acesso à fonte.(Mas esse é outro tópico.)

Para uma pessoa sem formação em ciência da computação, o que é um lambda no mundo da Ciência da Computação?

Vou ilustrá-lo intuitivamente, passo a passo, em códigos Python simples e legíveis.

Resumindo, um lambda é apenas uma função anônima e embutida.

Vamos começar pela tarefa para entender lambdas como um calouro com formação em aritmética básica.

O modelo de atribuição é 'o nome = valor', consulte:

In [1]: x = 1
   ...: y = 'value'
In [2]: x
Out[2]: 1
In [3]: y
Out[3]: 'value'

'x', 'y' são nomes e 1, 'valor' são valores.Experimente uma função em matemática

In [4]: m = n**2 + 2*n + 1
NameError: name 'n' is not defined

Relatórios de erros,
você não pode escrever uma matemática diretamente como código, 'n' deve ser definido ou atribuído a um valor.

In [8]: n = 3.14
In [9]: m = n**2 + 2*n + 1
In [10]: m
Out[10]: 17.1396

Funciona agora, e se você insistir em combinar as duas linhas separadas em uma.Lá vem lambda

In [13]: j = lambda i: i**2 + 2*i + 1
In [14]: j
Out[14]: <function __main__.<lambda>>

Nenhum erro relatado.

Este é um olhar para lambda, ele permite que você escreva uma função em uma única linha, como faz em matemática, diretamente no computador.

Veremos isso mais tarde.

Vamos continuar nos aprofundando na 'atribuição'.

Conforme ilustrado acima, o símbolo de igual = funciona para tipo de dados simples (1 e 'valor') e expressão simples (n**2 + 2*n + 1).

Experimente isto:

In [15]: x = print('This is a x')
This is a x
In [16]: x
In [17]: x = input('Enter a x: ')
Enter a x: x

Funciona para instruções simples, existem 11 tipos delas em python 7.Instruções simples — documentação do Python 3.6.3

Que tal declaração composta,

In [18]: m = n**2 + 2*n + 1 if n > 0
SyntaxError: invalid syntax
#or
In [19]: m = n**2 + 2*n + 1, if n > 0
SyntaxError: invalid syntax

Lá vem def permitir que funcione

In [23]: def m(n):
    ...:     if n > 0:
    ...:         return n**2 + 2*n + 1
    ...:
In [24]: m(2)
Out[24]: 9

Tada, analise, 'm' é nome, 'n**2 + 2*n + 1' é valor.: é uma variante de '='.
Encontre, nem que seja só para entender, tudo começa na atribuição e tudo é atribuição.

Agora volte para lambda, temos uma função chamada 'm'

Tentar:

In [28]: m = m(3)
In [29]: m
Out[29]: 16

Existem dois nomes de 'm' aqui, função m já tem um nome, duplicado.

Está formatando como:

In [27]: m = def m(n):
    ...:         if n > 0:
    ...:             return n**2 + 2*n + 1
    SyntaxError: invalid syntax

Não é uma estratégia inteligente, então relatórios de erros

Temos que deletar um deles, definir uma função sem nome.

m = lambda n:n**2 + 2*n + 1

É chamada de 'função anônima'

Para concluir,

  1. lambda em uma função inline que permite escrever uma função em uma linha reta, como faz na matemática
  2. lambda é anônimo

Espero que isto ajude.

É uma função que não tem nome.Por exemploem c# você pode usar

numberCollection.GetMatchingItems<int>(number => number > 5);

para retornar os números maiores que 5.

number => number > 5

é a parte lambda aqui.Representa uma função que recebe um parâmetro (número) e retorna um valor booleano (número> 5).O método GetMatchingItems usa esse lambda em todos os itens da coleção e retorna os itens correspondentes.

Em Javascript, por exemplo, as funções são tratadas como o mesmo tipo misto de todo o resto (int, string, float, bool).Dessa forma, você pode criar funções dinamicamente, atribuí-las a coisas e chamá-las de volta mais tarde.É útil, mas não é algo que você queira usar demais ou confundirá todos que precisam manter seu código depois de você ...

Este é um código com o qual eu estava brincando para ver a profundidade dessa toca do coelho:

var x = new Object;
x.thingy = new Array();
x.thingy[0] = function(){ return function(){ return function(){ alert('index 0 pressed'); }; }; }
x.thingy[1] = function(){ return function(){ return function(){ alert('index 1 pressed'); }; }; }
x.thingy[2] = function(){ return function(){ return function(){ alert('index 2 pressed'); }; }; }

for(var i=0 ;i<3; i++)
    x.thingy[i]()()();

No contexto do CS, uma função lambda é um conceito matemático abstrato que aborda um problema de avaliação simbólica de expressões matemáticas.Nesse contexto, uma função lambda é o mesmo que uma termo lambda.

Mas nas linguagens de programação é algo diferente.É um pedaço de código que é declarado “em vigor” e que pode ser repassado como um “cidadão de primeira classe”.Este conceito pareceu ser útil, de modo que entrou em quase todas as linguagens de programação modernas populares (veja funções lambda em todos os lugares publicar).

Eu também entendi.Eu tentei em JS com este:

var addAndMult = function(x) {
        return (function(y) {
            return (function(z) {
                return (x+y)*z; 
                });
            });
        };

Ele adiciona 2 a 4 e multiplica o resultado por 6.No entanto, às vezes acho difícil de ler :(

Também criei uma função forEach interessante:

var forEach = function(arr) {
            return (function(x) {
            for (var i=0; arr[i]; i++) {
                 x(arr[i]);
             }
        });
    }

forEach([1,2,3,4,5])(console.log);

Este método irá iterar um array e executar uma ação - no caso, imprimir no console.Agora eu também entendo porque os labmdas são poderosos.

Na programação de computadores, lambda é um trecho de código (declaração, expressão ou um grupo deles) que recebe alguns argumentos de uma fonte externa.Nem sempre deve ser uma função anônima - temos muitas maneiras de implementá-las.

Temos uma separação clara entre expressões, enunciados e funções, o que os matemáticos não possuem.

A palavra “função” em programação também é diferente – temos “função é uma série de etapas a serem executadas” (do latim “executar”).Em matemática é algo sobre correlação entre variáveis.

As linguagens funcionais estão tentando ser o mais semelhantes possível às fórmulas matemáticas, e suas palavras significam quase o mesmo.Mas em outras linguagens de programação é diferente.

A Lambda Function, ou um Small Anonymous Function, é um bloco independente de funcionalidade que pode ser transmitido e usado em seu código.Lambda tem nomes diferentes em diferentes linguagens de programação – Lambda em Pitão e Kotlin, Closure em Rápido, ou Block em C e Objetivo-C.Embora o significado de lambda seja bastante semelhante para essas línguas, às vezes há pequenas distinções.

Vamos ver como o Lambda (Closure) funciona no Swift 4.2 com o método sorted() – da função normal até a expressão mais curta:

let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]

1.Função normal

func backward(_ n1: String, _ n2: String) -> Bool {
    return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)


// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]

2.Expressão de Encerramento

reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in
    return n1 > n2
})

3.Expressão de fechamento embutido

reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 } )

4.Inferindo o tipo do contexto

reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )

5.Retornos implícitos de fechamentos de expressão única

reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )

6.Nomes abreviados de argumentos

reverseOrder = coffee.sorted(by: { $0 > $1 } )

// $0 and $1 are closure’s first and second String arguments.

7.Métodos de Operador

reverseOrder = coffee.sorted(by: >)

// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]

Espero que isto ajude.

A pergunta foi respondida na íntegra, não quero entrar em detalhes.Quero compartilhar o uso ao escrever cálculos numéricos em ferrugem.

Há um exemplo de lambda (função anônima)

let f = |x: f32| -> f32 { x * x - 2.0 };
let df = |x: f32| -> f32 { 2.0 * x };

Quando eu estava escrevendo um módulo do método Newton-Raphson, ele foi usado como derivada de primeira e segunda ordem.(Se você quiser saber o que é o método Newton-Raphson, visite "https://en.wikipedia.org/wiki/Newton%27s_method".

A saída como a seguir

println!("f={:.6}      df={:.6}", f(10.0), df(10.0))

f=98.000000       df=20.000000

Imagine que você tem um restaurante com opção de delivery e tem um pedido que precisa ser feito em menos de 30 minutos.A questão é que os clientes geralmente não se importam se você envia a comida de bicicleta, de carro ou descalço, desde que mantenha a refeição quente e amarrada.Então, vamos converter esse idioma para Javascript com funções de transporte anônimas e definidas.

Abaixo definimos a forma de entrega, também conhecido como definimos um nome para uma função:

// ES5 
var food = function withBike(kebap, coke) {
return (kebap + coke); 
};

E se usássemos funções arrow/lambda para realizar esta transferência:

// ES6    
const food = (kebap, coke) => { return kebap + coke };

Você vê que não há diferença para o cliente e não há perda de tempo pensando em como enviar comida.Basta enviar.

Aliás, eu não recomendo o kebap com cocaína, é por isso que os códigos superiores causarão erros.Divirta-se.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top