¿Qué es una lambda (función)?
Para una persona sin experiencia en ciencias de la computación, ¿qué es una lambda en el mundo de la informática?
Lambda proviene de Lambda Calculus y se refiere a funciones anónimas en programación.
¿Por qué es esto genial? Le permite escribir funciones rápidas y desechables sin nombrarlas. También proporciona una buena manera de escribir cierres. Con ese poder puedes hacer cosas como esta.
Pitón
def adder(x):
return lambda y: x + y
add5 = adder(5)
add5(1)
6
Como puede ver en el fragmento de Python, el sumador de funciones toma un argumento x y devuelve una función anónima, o lambda, que toma otro argumento y. Esa función anónima te permite crear funciones a partir de funciones. Este es un ejemplo simple, pero debería transmitir la potencia que tienen las lambdas y los cierres.
Ejemplos en otros idiomas
perla 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 o 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 = fn () => $a + $b;
echo $lambda();
Haskell
(\x y -> x + y)
Java ver esta publicación
// 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
Rubí
Ruby es ligeramente diferente en el sentido de que no se puede llamar a una lambda usando exactamente la misma sintaxis que para llamar a una función, pero aún tiene lambdas.
def adder(x)
lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6
Al ser Ruby Ruby, existe una abreviatura de lambdas, por lo que puedes definirla adder
de esta manera:
def adder(x)
-> y { x + y }
end
R
adder <- function(x) {
function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6
Una lambda es un tipo de función, definida en línea. Junto con una lambda, también suele tener algún tipo de variable que puede contener una referencia a una función, lambda o no.
Por ejemplo, aquí hay un fragmento de código C# que no utiliza una 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);
}
Esto llama a Calculadora, transmitiendo no solo dos números, sino también qué método llamar dentro de Calculadora para obtener los resultados del cálculo.
En C# 2.0 obtuvimos métodos anónimos, lo que acorta el código anterior 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;
});
}
Y luego en C# 3.0 obtuvimos lambdas, lo que hace que el código sea aún más corto:
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);
}
El nombre "lambda" es sólo un artefacto histórico. De lo único que estamos hablando es de una expresión cuyo valor es una función.
Un ejemplo sencillo (usando Scala para la siguiente línea) es:
args.foreach(arg => println(arg))
donde el argumento del foreach
método es una expresión para una función anónima. La línea anterior es más o menos lo mismo que escribir algo como esto (no es un código del todo real, pero entenderás la idea):
void printThat(Object that) {
println(that)
}
...
args.foreach(printThat)
excepto que no necesitas preocuparte por:
- Declarar la función en otro lugar (y tener que buscarla cuando vuelvas a visitar el código más adelante).
- Nombrar algo que solo estás usando una vez.
Una vez que estás acostumbrado a los valores de función, tener que prescindir de ellos parece tan tonto como tener que nombrar cada expresión, como por ejemplo:
int tempVar = 2 * a + b
...
println(tempVar)
en lugar de simplemente escribir la expresión donde la necesitas:
println(2 * a + b)
La notación exacta varía de un idioma a otro; ¡No siempre se requiere griego! ;-)