Per una persona senza un background di scienze informatiche, cos'è un lambda nel mondo dell'informatica?
Per una persona senza un background di scienze informatiche, cos'è un lambda nel mondo dell'informatica?
Risposte:
Lambda viene dal Lambda Calculus e si riferisce a funzioni anonime nella programmazione.
Perché è bello? Ti consente di scrivere funzioni di eliminazione rapida senza nominarle. Fornisce anche un bel modo di scrivere chiusure. Con quel potere puoi fare cose come questa.
Pitone
def adder(x):
return lambda y: x + y
add5 = adder(5)
add5(1)
6
Come puoi vedere dallo snippet di Python, l'adder di funzione accetta un argomento x e restituisce una funzione anonima, o lambda, che accetta un altro argomento y. Quella funzione anonima ti consente di creare funzioni da funzioni. Questo è un semplice esempio, ma dovrebbe trasmettere il potere che hanno lambda e chiusure.
Esempi in altre lingue
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
schema
(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);
veloce
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 vedi questo 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
Rubino
Ruby è leggermente diverso in quanto non è possibile chiamare un lambda usando la stessa sintassi esatta del chiamare una funzione, ma ha ancora lambdas.
def adder(x)
lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6
Ruby è Ruby, c'è una scorciatoia per lambdas, quindi puoi definire in adder
questo modo:
def adder(x)
-> y { x + y }
end
R
adder <- function(x) {
function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6
Una lambda è un tipo di funzione, definita in linea. Insieme a un lambda di solito hai anche un qualche tipo di tipo variabile che può contenere un riferimento a una funzione, lambda o altro.
Ad esempio, ecco un pezzo di codice C # che non usa un 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);
}
Questo chiama Calcolatrice, passando non solo due numeri, ma quale metodo chiamare all'interno della Calcolatrice per ottenere i risultati del calcolo.
In C # 2.0 abbiamo metodi anonimi, che accorciano il codice sopra a:
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 poi in C # 3.0 abbiamo ottenuto lambdas che rende il codice ancora più breve:
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
, si può semplicemente usareFunc<int, int>
Console.WriteLine("Calculator: op " + op.Method.Name + " (" + a + ", " + b + ") = " + op(a, b));
per il primo esempio.
Il nome "lambda" è solo un manufatto storico. Tutto ciò di cui stiamo parlando è un'espressione il cui valore è una funzione.
Un semplice esempio (usando Scala per la riga successiva) è:
args.foreach(arg => println(arg))
dove l'argomento del foreach
metodo è un'espressione per una funzione anonima. La riga sopra è più o meno la stessa di scrivere qualcosa del genere (codice non proprio reale, ma otterrai l'idea):
void printThat(Object that) {
println(that)
}
...
args.foreach(printThat)
tranne che non devi preoccuparti di:
Una volta che sei abituato a utilizzare i valori, doverne fare a meno sembra sciocco come essere richiesto per nominare ogni espressione, come ad esempio:
int tempVar = 2 * a + b
...
println(tempVar)
invece di scrivere semplicemente l'espressione dove serve:
println(2 * a + b)
La notazione esatta varia da lingua a lingua; Il greco non è sempre richiesto! ;-)
Si riferisce al calcolo lambda , che è un sistema formale che ha solo espressioni lambda, che rappresentano una funzione che accetta una funzione per il suo unico argomento e restituisce una funzione. Tutte le funzioni nel calcolo lambda sono di quel tipo, ovveroλ : λ → λ
.
Lisp usò il concetto lambda per nominare i suoi letterali funzione anonima. Questa lambda rappresenta una funzione che accetta due argomenti, xey, e restituisce il loro prodotto:
(lambda (x y) (* x y))
Può essere applicato in linea in questo modo (valuta 50 ):
((lambda (x y) (* x y)) 5 10)
λ : λ -> λ
sia confuso (e in realtà non valido).
Il calcolo lambda è una coerente teoria matematica della sostituzione. Nella matematica della scuola si vede ad esempio un x+y=5
abbinamentox−y=1
. Oltre ai modi di manipolare le singole equazioni è anche possibile mettere insieme le informazioni di questi due, a condizione che le sostituzioni di equazioni incrociate vengano eseguite logicamente. Il calcolo lambda codifica il modo corretto di effettuare queste sostituzioni.
Dato che si y = x−1
tratta di un riarrangiamento valido della seconda equazione, questo: λ y = x−1
significa una funzione che sostituisce i simboli x−1
con il simbolo y
. Ora immagina di applicare λ y
ad ogni termine nella prima equazione. Se un termine viene y
quindi eseguito la sostituzione; altrimenti non fare nulla. Se lo fai su carta vedrai come applicarloλ y
renderà risolvibile la prima equazione.
Questa è una risposta senza alcuna informatica o programmazione.
L'esempio di programmazione più semplice che mi viene in mente viene da http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works :
ecco come la funzione quadrata potrebbe essere definita in un linguaggio di programmazione imperativo (C):
int square(int x) { return x * x; }
La variabile x è un parametro formale che viene sostituito dal valore effettivo da quadrare quando viene chiamata la funzione. In un linguaggio funzionale (Schema) sarebbe definita la stessa funzione:
(define square (lambda (x) (* x x)))
Questo è diverso in molti modi, ma usa ancora il parametro formale x allo stesso modo.
Aggiunto: http://imgur.com/a/XBHub
Leggermente semplificato: una funzione lambda è una funzione che può essere passata ad altre funzioni e alla quale si accede alla logica.
In C # la sintassi lambda è spesso compilata con metodi semplici allo stesso modo dei delegati anonimi, ma può anche essere scomposta e la sua logica letta.
Ad esempio (in C # 3):
LinqToSqlContext.Where(
row => row.FieldName > 15 );
LinqToSql può leggere quella funzione (x> 15) e convertirla nell'SQL effettivo per eseguirla usando gli alberi delle espressioni.
La dichiarazione sopra diventa:
select ... from [tablename]
where [FieldName] > 15 --this line was 'read' from the lambda function
Questo è diverso dai metodi normali o dai delegati anonimi (che in realtà sono solo magie del compilatore) perché non possono essere letti .
Non tutti i metodi in C # che usano la sintassi lambda possono essere compilati negli alberi delle espressioni (ovvero funzioni lambda effettive). Per esempio:
LinqToSqlContext.Where(
row => SomeComplexCheck( row.FieldName ) );
Ora l'albero delle espressioni non può essere letto - SomeComplexCheck non può essere scomposto. L'istruzione SQL verrà eseguita senza il dove e verrà passata ogni riga nei dati SomeComplexCheck
.
Le funzioni Lambda non devono essere confuse con metodi anonimi. Per esempio:
LinqToSqlContext.Where(
delegate ( DataRow row ) {
return row.FieldName > 15;
} );
Anche questa ha una funzione 'inline', ma questa volta è solo magia del compilatore - il compilatore C # lo suddividerà in un nuovo metodo di istanza con un nome generato automaticamente.
I metodi anonimi non possono essere letti, quindi la logica non può essere tradotta come per le funzioni lambda.
Mi piace la spiegazione di Lambdas in questo articolo: L'evoluzione di LINQ e il suo impatto sul design di C # . Ha avuto molto senso per me in quanto mostra un mondo reale per Lambdas e lo costruisce come un esempio pratico.
La loro rapida spiegazione: i lambda sono un modo per trattare il codice (funzioni) come dati.
Un esempio di lambda in Ruby è il seguente:
hello = lambda do
puts('Hello')
puts('I am inside a proc')
end
hello.call
Genererà il seguente output:
Hello
I am inside a proc
@Brian Uso lambdas sempre in C #, in operatori LINQ e non LINQ. Esempio:
string[] GetCustomerNames(IEnumerable<Customer> customers)
{ return customers.Select(c=>c.Name);
}
Prima di C #, utilizzavo funzioni anonime in JavaScript per richiamare le funzioni AJAX, prima ancora che il termine Ajax fosse coniato:
getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/});
La cosa interessante con la sintassi lambda di C #, tuttavia, è che da soli il loro tipo non può essere dedotto (cioè, non è possibile digitare var foo = (x, y) => x * y) ma a seconda del tipo di assegnati a, verranno compilati come delegati o alberi di sintassi astratti che rappresentano l'espressione (che è il modo in cui i mappatori di oggetti LINQ eseguono la loro magia "integrata nel linguaggio").
Lambdas in LISP può anche essere passato a un operatore di quotazione e quindi attraversato come un elenco di elenchi. Alcune macro potenti sono realizzate in questo modo.
Alla domanda viene formalmente data una grande risposta, quindi non proverò ad aggiungere altro su questo.
In parole molto semplici e informali a qualcuno che sa molto poco o nulla di matematica o programmazione, lo spiegherei come una piccola "macchina" o "scatola" che accetta input, fa funzionare e produce output, non ha un nome particolare , ma sappiamo dove si trova e proprio con questa conoscenza, la usiamo.
In pratica, per una persona che sa cos'è una funzione, direi che è una funzione senza nome, solitamente messa a un punto nella memoria che può essere utilizzata semplicemente facendo riferimento a quella memoria (di solito tramite l'uso di una variabile - se avessero sentito parlare del concetto dei puntatori a funzione, li userei come un concetto simile) - questa risposta copre le basi piuttosto carine (nessuna menzione di chiusure ecc.) ma si può facilmente capire il punto.
Puoi pensarlo come una funzione anonima - ecco alcune altre informazioni: Wikipedia - Funzione anonima
Solo perché non riesco a vedere un esempio C ++ 11 qui, vado avanti e posterò questo bell'esempio da qui . Dopo la ricerca, è l'esempio specifico di linguaggio più chiaro che ho trovato.
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();
}
Ho problemi ad avvolgere la testa attorno alle espressioni lambda perché lavoro in Visual FoxPro, che ha la sostituzione Macro e le funzioni ExecScript {} e Evaluate (), che sembrano avere più o meno lo stesso scopo.
? Calculator(10, 23, "a + b")
? Calculator(10, 23, "a - b");
FUNCTION Calculator(a, b, op)
RETURN Evaluate(op)
Un vantaggio decisivo nell'uso di lambda formali è (presumo) il controllo in fase di compilazione: Fox non saprà se si digita la stringa di testo sopra finché non tenta di eseguirla.
Ciò è utile anche per il codice basato sui dati: è possibile archiviare intere routine nei campi memo nel database e quindi valutarli in fase di esecuzione. Ciò ti consente di modificare parte dell'applicazione senza avere effettivamente accesso all'origine. (Ma questo è un altro argomento del tutto.)
Per una persona senza un background di scienze informatiche, cos'è un lambda nel mondo dell'informatica?
Lo illustrerò in modo intuitivo passo dopo passo in codici pitone semplici e leggibili.
In breve, una lambda è solo una funzione anonima e in linea.
Partiamo dall'incarico per capire lambdas
come una matricola con un background di aritmetica di base.
Il progetto dell'assegnazione è 'il nome = valore', vedi:
In [1]: x = 1
...: y = 'value'
In [2]: x
Out[2]: 1
In [3]: y
Out[3]: 'value'
'x', 'y' sono nomi e 1, 'valore' sono valori. Prova una funzione in matematica
In [4]: m = n**2 + 2*n + 1
NameError: name 'n' is not defined
Segnalazioni di errori,
non è possibile scrivere una matematica direttamente come codice, 'n' deve essere definito o assegnato a un valore.
In [8]: n = 3.14
In [9]: m = n**2 + 2*n + 1
In [10]: m
Out[10]: 17.1396
Funziona ora, e se insisti nel combinare le due linee seperarte con una. Arrivalambda
In [13]: j = lambda i: i**2 + 2*i + 1
In [14]: j
Out[14]: <function __main__.<lambda>>
Nessun errore segnalato.
Questo è uno sguardo a lambda
, ti permette di scrivere una funzione su una sola riga come fai direttamente in matematica nel computer.
Lo vedremo più tardi.
Continuiamo a scavare più a fondo sull'assegnazione.
Come illustrato sopra, il simbolo uguale =
funziona per tipo di dati semplici (1 e 'valore') ed espressione semplice (n ** 2 + 2 * n + 1).
Prova questo:
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
Funziona con semplici istruzioni, ce ne sono 11 tipi in Python 7. semplici - Documentazione di Python 3.6.3
Che ne dici di dichiarazione 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
Arriva def
abilitarlo a funzionare
In [23]: def m(n):
...: if n > 0:
...: return n**2 + 2*n + 1
...:
In [24]: m(2)
Out[24]: 9
Tada, analizzalo, 'm' è nome, 'n ** 2 + 2 * n + 1' è valore. :
è una variante di '='.
Trovalo, anche solo per capire, tutto parte dall'incarico e tutto è incarico.
Ora torna a lambda
, abbiamo una funzione chiamata 'm'
Provare:
In [28]: m = m(3)
In [29]: m
Out[29]: 16
Ci sono due nomi di 'm' qui, la funzione m
ha già un nome, duplicata.
È formattato come:
In [27]: m = def m(n):
...: if n > 0:
...: return n**2 + 2*n + 1
SyntaxError: invalid syntax
Non è una strategia intelligente, quindi segnala errori
Dobbiamo eliminarne uno, impostare una funzione senza nome.
m = lambda n:n**2 + 2*n + 1
Si chiama "funzione anonima"
In conclusione,
lambda
in una funzione in linea che ti consente di scrivere una funzione in una linea retta come in matematicalambda
è anonimoSpero che sia di aiuto.
È una funzione che non ha nome. Ad esempio in c # puoi usare
numberCollection.GetMatchingItems<int>(number => number > 5);
per restituire i numeri maggiori di 5.
number => number > 5
è la parte lambda qui. Rappresenta una funzione che accetta un parametro (numero) e restituisce un valore booleano (numero> 5). Il metodo GetMatchingItems utilizza questo lambda su tutti gli elementi della raccolta e restituisce gli elementi corrispondenti.
In JavaScript, ad esempio, le funzioni vengono trattati come lo stesso tipo misto come tutto il resto ( int
, string
, float
, bool
). Pertanto, è possibile creare funzioni al volo, assegnarle alle cose e richiamarle in seguito. È utile, ma non qualcosa che vuoi usare eccessivamente o confonderai tutti coloro che devono mantenere il codice dopo di te ...
Questo è un codice con cui stavo giocando per vedere quanto è profonda questa tana del coniglio:
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]()()();
Nel contesto di CS una funzione lambda è un concetto matematico astratto che affronta un problema di valutazione simbolica di espressioni matematiche. In quel contesto una funzione lambda è la stessa di un termine lambda .
Ma nei linguaggi di programmazione è qualcosa di diverso. È un pezzo di codice che viene dichiarato "in atto" e che può essere trasmesso come "cittadino di prima classe". Questo concetto sembrava essere utile in modo che entrasse in quasi tutti i linguaggi di programmazione moderni più diffusi (vedi le funzioni lambda ovunque ).
A
Lambda Function
o aSmall Anonymous Function
è un blocco autonomo di funzionalità che può essere passato in giro e utilizzato nel codice. Lambda ha nomi diversi in diversi linguaggi di programmazione:Lambda
in Python e Kotlin ,Closure
in Swift oBlock
in C e Objective-C . Sebbene il significato di lambda sia abbastanza simile per queste lingue, a volte presenta lievi distinzioni.
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"]
Spero che sia di aiuto.
L'ho preso anch'io. L'ho provato in JS con questo:
var addAndMult = function(x) {
return (function(y) {
return (function(z) {
return (x+y)*z;
});
});
};
Aggiunge da 2 a 4, quindi mostra il risultato per 6. Tuttavia, a volte trovo difficile leggere :(
Inoltre ho creato un'interessante funzione per ogni funzione:
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);
Questo metodo eseguirà l'iterazione di un array ed eseguirà un'azione, nel caso in cui la stampa venga eseguita sulla console. Ora capisco anche perché i labmda sono potenti.
Nella programmazione per computer, lambda è un pezzo di codice (istruzione, espressione o un gruppo di essi) che accetta alcuni argomenti da una fonte esterna. Non deve sempre essere una funzione anonima: abbiamo molti modi per implementarli.
Abbiamo una netta separazione tra espressioni, dichiarazioni e funzioni, che i matematici non hanno.
Anche la parola "funzione" in programmazione è diversa - abbiamo "funzione è una serie di passaggi da fare" (dal latino "eseguire"). In matematica si tratta di correlazione tra variabili.
I linguaggi funzionali stanno cercando di essere il più possibile simili alle formule matematiche e le loro parole significano quasi lo stesso. Ma in altri linguaggi di programmazione lo abbiamo diverso.
Alla domanda è stata data una risposta completa, non voglio entrare nei dettagli. Voglio condividere l'uso quando si scrive il calcolo numerico in ruggine.
C'è un esempio di lambda (funzione anonima)
let f = |x: f32| -> f32 { x * x - 2.0 };
let df = |x: f32| -> f32 { 2.0 * x };
Quando stavo scrivendo un modulo del metodo Newton-Raphson, veniva usato come derivato del primo e del secondo ordine. (Se vuoi sapere cos'è il metodo Newton-Raphson, visita " https://en.wikipedia.org/wiki/Newton%27s_method ".
L'output è il seguente
println!("f={:.6} df={:.6}", f(10.0), df(10.0))
f=98.000000 df=20.000000
Immagina di avere un ristorante con un'opzione di consegna e di avere un ordine che deve essere eseguito in meno di 30 minuti. Il punto è che i clienti di solito non si preoccupano se si invia il loro cibo in bici con una macchina o a piedi nudi finché si mantiene il pasto caldo e legato. Quindi, consente di convertire questo linguaggio in Javascript con funzioni di trasporto anonime e definite.
Di seguito abbiamo definito la modalità di consegna, ovvero definiamo un nome per una funzione:
// ES5
var food = function withBike(kebap, coke) {
return (kebap + coke);
};
E se utilizzassimo le funzioni freccia / lambda per eseguire questo trasferimento:
// ES6
const food = (kebap, coke) => { return kebap + coke };
Vedi che non c'è differenza per il cliente e non perdi tempo a pensare a come inviare cibo. Mandalo e basta.
A proposito, non consiglio il kebap con coke, ecco perché i codici superiori ti daranno errori. Divertiti.