Para uma pessoa sem formação em ficção científica, o que é uma lambda no mundo da Ciência da Computação?
Para uma pessoa sem formação em ficção científica, o que é uma lambda no mundo da Ciência da Computação?
Respostas:
O Lambda é derivado do Cálculo do Lambda e refere-se a funções anônimas na 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 boa maneira de escrever fechamentos. 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 snippet do Python, o adicionador de função recebe um argumento x e retorna uma função anônima, ou lambda, que usa outro argumento y. Essa função anônima permite criar funções a partir de funções. Este é um exemplo simples, mas deve transmitir a potência que os lambdas e os 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
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 = fn () => $a + $b;
echo $lambda();
Haskell
(\x y -> x + y)
Java veja este post
// 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, pois você não pode chamar um lambda usando exatamente a mesma sintaxe que chamar 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
desta maneira:
def adder(x)
-> y { x + y }
end
R
adder <- function(x) {
function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6
Um lambda é um tipo de função definida em linha. Juntamente com um lambda, você também costuma ter algum tipo de variável que pode conter uma referência a uma função, lambda ou de outra forma.
Por exemplo, aqui está um código C # que não usa um 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 a Calculadora, transmitindo não apenas dois números, mas qual método chamar dentro da Calculadora para obter os resultados do cálculo.
No C # 2.0, temos métodos anônimos, que reduzem 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, temos 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);
}
Op
, pode-se simplesmente usarFunc<int, int>
Console.WriteLine("Calculator: op " + op.Method.Name + " (" + a + ", " + b + ") = " + op(a, b));
o primeiro exemplo.
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 a mesma coisa que escrever algo assim (código não muito real, mas você entenderá):
void printThat(Object that) {
println(that)
}
...
args.foreach(printThat)
exceto que você não precisa se preocupar com:
Depois que você estiver acostumado a funcionar com valores, ficar sem eles parece tão tolo quanto precisar nomear todas as expressões, como:
int tempVar = 2 * a + b
...
println(tempVar)
em vez de apenas escrever a expressão onde você precisar:
println(2 * a + b)
A notação exata varia de idioma para idioma; Grego nem sempre é necessário! ;-)
Refere-se ao cálculo lambda , que é um sistema formal que apenas possui expressões lambda, que representam uma função que utiliza uma função para seu ú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ônimos. Este lambda representa uma função que recebe dois argumentos, xey, e retorna seu produto:
(lambda (x y) (* x y))
Pode ser aplicado em linha assim (avalia para 50 ):
((lambda (x y) (* x y)) 5 10)
λ : λ -> λ
é confuso (e inválido, na verdade).
O cálculo lambda é uma teoria matemática consistente de substituição. Na matemática da escola, vê-se, por exemplo, x+y=5
emparelhado x−y=1
. Juntamente 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 logicamente. 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, isso: λ y = x−1
significa uma função que substitui os símbolos x−1
pelo símbolo y
. Agora imagine aplicar λ y
a cada termo na primeira equação. Se um termo for y
, execute a substituição; caso contrário, não faça nada. Se você fizer isso no papel, verá como a aplicação disso λ 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_language)#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 elevado ao 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 em muitos aspectos, mas ainda usa o parâmetro formal x da mesma maneira.
Adicionado: http://imgur.com/a/XBHub
Ligeiramente simplificado: uma função lambda é aquela que pode ser passada para outras funções e é acessada pela lógica.
No C #, a sintaxe lambda geralmente é compilada para métodos simples da mesma maneira que os 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 );
O 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 se torna:
select ... from [tablename]
where [FieldName] > 15 --this line was 'read' from the lambda function
Isso é diferente dos métodos normais ou dos delegados anônimos (que são apenas magias do compilador), porque eles não podem ser lidos .
Nem todos os métodos em C # que usam sintaxe lambda podem ser compilados para árvores de expressão (ou seja, funções reais lambda). Por exemplo:
LinqToSqlContext.Where(
row => SomeComplexCheck( row.FieldName ) );
Agora a árvore de expressão não pode ser lida - SomeComplexCheck não pode ser dividido. A instrução SQL será executada sem o where e todas as linhas dos dados serão inseridas 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.
Os métodos anônimos não podem ser lidos e, portanto, a lógica não pode ser traduzida como nas funções lambda.
Gosto da explicação de Lambdas neste artigo: A evolução do LINQ e seu impacto no design de c # . Isso fez muito sentido para mim, pois mostra um mundo real para Lambdas e o constrói como um exemplo prático.
Sua rápida explicação: Lambdas são uma maneira 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 do 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 de qual tipo eles são atribuídos a eles, eles serão compilados como delegados ou árvores de sintaxe abstrata que representam a expressão (é assim que os mapeadores de objetos LINQ fazem sua mágica "integrada ao idioma").
Lambdas no LISP também podem ser passadas para um operador de cotação e depois percorridas como uma lista de listas. Algumas macros poderosas são criadas dessa maneira.
A pergunta é formalmente respondida bastante, por isso não tentarei acrescentar mais sobre isso.
Em palavras muito simples e informais para alguém que sabe muito pouco ou nada sobre 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, sem nome específico , mas sabemos onde está e, justamente por esse conhecimento, nós o usamos.
Na prática, para uma pessoa que sabe o que é uma função, eu diria a ela que é uma função que não tem nome, geralmente colocada em um ponto na memória que pode ser usado apenas fazendo referência a essa memória (geralmente através do uso de uma variável - se eles ouviram falar sobre o conceito de ponteiros de função, eu os usaria como um conceito semelhante) - esta resposta cobre os princípios básicos (sem menção de fechamentos etc.), mas é possível entender o ponto facilmente.
Você pode pensar nisso como uma função anônima - eis mais algumas informações: Wikipedia - Função Anônima
Só porque não consigo ver um exemplo de C ++ 11 aqui, vou adiante e postarei este bom exemplo daqui . Após a pesquisa, é o exemplo específico de idioma mais claro que eu pude encontrar.
template<typename F>
void Eval( const F& f ) {
f();
}
void foo() {
Eval( []{ printf("Hello, Lambdas\n"); } );
}
void bar() {
auto f = []{ printf("Hello, Lambdas\n"); };
f();
}
Tenho problemas para entender expressões lambda porque trabalho no Visual FoxPro, que possui substituição de macro e as funções ExecScript {} e Evaluate (), que parecem servir 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: a Fox não saberá se você digitar a sequência de texto acima até tentar executá-la.
Isso também é útil para código orientado a 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 que você ajuste parte do aplicativo sem realmente ter acesso à fonte. (Mas esse é outro tópico completamente.)
Para uma pessoa sem formação em ficção científica, o que é uma lambda no mundo da Ciência da Computação?
Ilustrarei intuitivamente passo a passo em códigos python simples e legíveis.
Em resumo, um lambda é apenas uma função anônima e inline.
Vamos começar da tarefa de entender lambdas
como um calouro com conhecimentos básicos de aritmética.
O plano 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. Tente uma função em matemática
In [4]: m = n**2 + 2*n + 1
NameError: name 'n' is not defined
Relatórios de erro,
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 seperarte em uma. Lá vemlambda
In [13]: j = lambda i: i**2 + 2*i + 1
In [14]: j
Out[14]: <function __main__.<lambda>>
Nenhum erro relatado.
Este é um relance lambda
, permite que você escreva uma função em uma única linha, como na matemática diretamente no computador.
Veremos mais tarde.
Vamos continuar a aprofundar a tarefa.
Como ilustrado acima, o símbolo de igual =
funciona para o tipo de dados simples (1 e 'valor') e expressão simples (n ** 2 + 2 * n + 1).
Tente o seguinte:
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 no 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
Aí vem def
habilitá-lo a trabalhar
In [23]: def m(n):
...: if n > 0:
...: return n**2 + 2*n + 1
...:
In [24]: m(2)
Out[24]: 9
Tada, analise, 'm' é o nome, 'n ** 2 + 2 * n + 1' é o valor. :
é uma variante de '='.
Encontre, se apenas para entender, tudo começa com a atribuição e tudo é atribuição.
Agora retorne a 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, a 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 os relatórios de erros
Temos que excluir um deles, definir uma função sem nome.
m = lambda n:n**2 + 2*n + 1
É chamado de 'função anônima'
Em conclusão,
lambda
em uma função embutida que permite escrever uma função em uma linha reta, como na matemáticalambda
é anônimoEspero que isto ajude.
É uma função que não tem nome. Por exemplo, em 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 pega 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 como tudo o resto ( int
, string
, float
, bool
). Como tal, você pode criar funções em tempo real, atribuí-las a coisas e chamá-las de volta mais tarde. É útil, mas não é algo que você deseja usar em excesso ou confundirá todos que precisam manter seu código depois de você ...
Este é um código com o qual eu estava jogando para ver a profundidade dessa toca de 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 é igual a um termo lambda .
Mas nas linguagens de programação é algo diferente. É um pedaço de código declarado "no lugar" e que pode ser passado como um "cidadão de primeira classe". Esse conceito pareceu ser útil para que ele chegasse a quase todas as linguagens de programação modernas populares (consulte as funções lambda em todo lugar)
A
Lambda Function
, ou aSmall Anonymous Function
, é um bloco de funcionalidade independente que pode ser transmitido e usado em seu código. O Lambda tem nomes diferentes em diferentes linguagens de programação -Lambda
em Python e Kotlin ,Closure
em Swift ouBlock
em C e Objective-C . Embora o significado de lambda seja bastante semelhante para essas línguas, às vezes há pequenas distinções.
let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]
func backward(_ n1: String, _ n2: String) -> Bool {
return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in
return n1 > n2
})
reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 } )
reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )
reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )
reverseOrder = coffee.sorted(by: { $0 > $1 } )
// $0 and $1 are closure’s first and second String arguments.
reverseOrder = coffee.sorted(by: >)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
Espero que isto ajude.
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 depois reduz o resultado por 6. No entanto, às vezes acho difícil 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);
Esse método itera uma matriz e executa uma ação - no caso, imprimindo no console. Agora eu também entendo por que os labmdas são poderosos.
Na programação de computadores, lambda é um pedaço 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 várias maneiras de implementá-las.
Temos uma separação clara entre expressões, afirmações e funções, que os matemáticos não possuem.
A palavra "função" na programação também é diferente - nós temos "função é uma série de etapas a serem executadas" (do latim "executar"). Em matemática, é algo sobre correlação entre variáveis.
Linguagens funcionais estão tentando ser o mais semelhante possível às fórmulas matemáticas, e suas palavras significam quase o mesmo. Mas em outras linguagens de programação, temos diferentes.
A pergunta foi respondida completamente, não quero entrar em detalhes. Quero compartilhar o uso ao escrever computação numérica com 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 escrevia um módulo do método Newton-Raphson, ele era 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 seguinte
println!("f={:.6} df={:.6}", f(10.0), df(10.0))
f=98.000000 df=20.000000
Imagine que você tem um restaurante com uma opção de entrega e um pedido que precisa ser feito em menos de 30 minutos. O ponto é que os clientes geralmente não se importam se você envia comida de bicicleta com o carro ou com os pés descalços, desde que mantenha a refeição quente e amarrada. Então, vamos converter esse idioma para Javascript com funções de transporte definidas e anônimas.
Abaixo, definimos a forma de entrega, ou seja, 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 essa 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 para pensar em como enviar comida. Apenas envie.
Aliás, eu não recomendo o kebap com coca-cola, é por isso que os códigos superiores causam erros. Diverta-se.