¿Qué es una lambda (función)?


Respuestas:


1081

Lambda proviene del cálculo Lambda y se refiere a funciones anónimas en la programación.

¿Por qué es esto genial? Le permite escribir funciones de descarte rápido 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 le permite crear funciones a partir de funciones. Este es un ejemplo simple, pero debe transmitir el poder que tienen las lambdas y los cierres.

Ejemplos en otros 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 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 la misma sintaxis exacta que llamar a una función, pero aún tiene lambdas.

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

Ruby siendo Ruby, hay una abreviatura de lambdas, por lo que puede definir de adderesta manera:

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

R

adder <- function(x) {
  function(y) x + y
}
add5 <- adder(5)
add5(1)
#> [1] 6

3
¿Cuál es la diferencia, entonces, entre una función lambda y un functor ?
Maxpm

1
@Maxpm un functor puede ser un objeto estándar con campos de instancia y funciones, mientras que una función lambda generalmente solo consta de una línea de instrucciones. Esto puede variar según el idioma, por supuesto.
zdimension

1
No creo que sea necesariamente preciso decir que las funciones lambda son las mismas que las funciones anónimas. Para algunos lenguajes como JavaScript, una expresión lambda es una forma específica de una función anónima. El ejemplo de JavaScript que proporcionó es una función anónima sin sintaxis lambda, mientras que el ejemplo de JavaScript (ES6) que proporcionó es una expresión lambda.
Kyle Delaney

1
@KyleDelaney, de hecho, el anonimato no es una condición necesaria para ser un lambda, de hecho, hay funciones lambda que no son anónimas, como se señala allí incluso en el ejemplo
Carmine Tambascia

@AliAnkarali o acostumbrarse a usar rubys lambda;)
Jimmy MG Lim

107

Una lambda es un tipo de función, definida en línea. Junto con una lambda, también suele tener algún tipo de tipo variable que puede contener una referencia a una función, lambda o de otro tipo.

Por ejemplo, aquí hay un código de C # que no usa 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, pasando no solo dos números, sino a qué método llamar dentro de Calculadora para obtener los resultados del cálculo.

En C # 2.0 tenemos métodos anónimos, que acortan el código anterior 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;
    });
}

Y luego en C # 3.0 tenemos lambdas 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);
}

En lugar de definir explícitamente al delegado Op, uno simplemente puede usarFunc<int, int>
Mateen Ulhaq

Sugeriría Console.WriteLine("Calculator: op " + op.Method.Name + " (" + a + ", " + b + ") = " + op(a, b));para el primer ejemplo.
Marc.2377

Tan sorprendente como la respuesta aceptada es ayudar a las personas en muchos idiomas diferentes, siento que esta respuesta me ayuda a comprender mejor la ventaja de las lambdas y cómo son diferentes de una función estándar. Puedo ver claramente aquí la ventaja de una lambda sobre los métodos anteriores para obtener un resultado similar.
RTHarston

Gracias por su ejemplo, tener una función más compleja ayuda a comprender las ventajas de las lambdas mucho más que las funciones simples donde parece que no obtiene mucha optimización
Sarah

72

El nombre "lambda" es solo un artefacto histórico. Todo lo que estamos hablando es una expresión cuyo valor es una función.

Un ejemplo simple (usando Scala para la siguiente línea) es:

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

donde el argumento del foreachmé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 real, pero se dará cuenta de la idea):

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

excepto que no necesitas molestarte con:

  1. Declarar la función en otro lugar (y tener que buscarla cuando vuelva a visitar el código más adelante).
  2. Nombrar algo que solo estás usando una vez.

Una vez que está acostumbrado a los valores de función, tener que prescindir de ellos parece tan tonto como se requiere para nombrar cada expresión, como:

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; ¡El griego no siempre es obligatorio! ;-)


62

Se refiere al cálculo lambda , que es un sistema formal que solo tiene expresiones lambda, que representan una función que toma una función como único argumento y devuelve una función. Todas las funciones en el cálculo lambda son de ese tipo, es decir, λ : λ → λ.

Lisp usó el concepto lambda para nombrar sus literales anónimos de función. Esta lambda representa una función que toma dos argumentos, x e y, y devuelve su producto:

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

Se puede aplicar en línea de esta manera (se evalúa en 50 ):

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

Creo que su uso de λ : λ -> λes confuso (e inválido en realidad).
einpoklum

52

El cálculo lambda es una teoría matemática consistente de sustitución. En las matemáticas de la escuela se ve, por ejemplo, x+y=5emparejado x−y=1. Junto con las formas de manipular ecuaciones individuales, también es posible reunir la información de estas dos, siempre que las sustituciones de ecuaciones cruzadas se realicen de forma lógica. El cálculo de Lambda codifica la forma correcta de hacer estas sustituciones.

Dado que y = x−1es una reorganización válida de la segunda ecuación, esto: λ y = x−1significa una función que sustituye los símbolos x−1por el símbolo y. Ahora imagine aplicar λ ya cada término en la primera ecuación. Si un término es, yentonces realice la sustitución; de lo contrario no hagas nada. Si haces esto en papel, verás cómo aplicarlo λ yhará que la primera ecuación sea solucionable.

Esa es una respuesta sin ninguna ciencia informática o programación.

El ejemplo de programación más simple que se me ocurre proviene de http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works :

Así es como se podría definir la función cuadrada en un lenguaje de programación imperativo (C):

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

La variable x es un parámetro formal que se reemplaza por el valor real al cuadrado cuando se llama a la función. En un lenguaje funcional (Esquema) se definiría la misma función:

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

Esto es diferente en muchos aspectos, pero aún utiliza el parámetro formal x de la misma manera.


Añadido: http://imgur.com/a/XBHub

lambda


14

Ligeramente simplificado: una función lambda es una que se puede pasar a otras funciones y se accede a ella lógicamente.

En C #, la sintaxis lambda a menudo se compila en métodos simples de la misma manera que los delegados anónimos, pero también se puede desglosar y leer su lógica.

Por ejemplo (en C # 3):

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

LinqToSql puede leer esa función (x> 15) y convertirla al SQL real para ejecutarla utilizando árboles de expresión.

La declaración anterior se convierte en:

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

Esto es diferente de los métodos normales o de los delegados anónimos (que en realidad son solo magia de compilación) porque no se pueden leer .

No todos los métodos en C # que usan la sintaxis lambda pueden compilarse en árboles de expresión (es decir, funciones lambda reales). Por ejemplo:

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

Ahora el árbol de expresión no se puede leer: SomeComplexCheck no se puede desglosar. La instrucción SQL se ejecutará sin el dónde, y cada fila de los datos se colocará SomeComplexCheck.

Las funciones de Lambda no deben confundirse con los métodos anónimos. Por ejemplo:

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

Esto también tiene una función 'en línea', pero esta vez es solo magia del compilador: el compilador de C # dividirá esto en un nuevo método de instancia con un nombre autogenerado.

Los métodos anónimos no se pueden leer, por lo que la lógica no se puede traducir como se puede para las funciones lambda.



7

Un ejemplo de lambda en Ruby es el siguiente:

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

hello.call

Generará el siguiente resultado:

Hello
I am inside a proc

6

La pregunta se responde formalmente en gran medida, por lo que no intentaré agregar más sobre esto.

En palabras muy simples e informales para alguien que sabe muy poco o nada de matemáticas o programación, lo explicaría como una pequeña "máquina" o "caja" que toma algo de entrada, hace algo de trabajo y produce algo de salida, no tiene un nombre en particular , pero sabemos dónde está y solo con este conocimiento, lo usamos.

Hablando en términos prácticos, para una persona que sabe lo que es una función, les diría que es una función que no tiene nombre, por lo general colocada en un punto en la memoria que puede usarse simplemente haciendo referencia a esa memoria (generalmente a través del uso de una variable, si han escuchado sobre el concepto de los punteros de función, los usaría como un concepto similar), esta respuesta cubre los conceptos básicos (no se mencionan los cierres, etc.) pero uno puede entender el punto fácilmente.


5

@Brian Yo uso lambdas todo el tiempo en C #, en operadores LINQ y no LINQ. Ejemplo:

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

Antes de C #, usaba funciones anónimas en JavaScript para devoluciones de llamada a funciones AJAX, incluso antes de que se acuñara el término Ajax:

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

Sin embargo, lo interesante de la sintaxis lambda de C # es que, por sí solos, su tipo no se puede inferir (es decir, no se puede escribir var foo = (x, y) => x * y) pero dependiendo de qué tipo son asignados a, se compilarán como delegados o árboles de sintaxis abstracta que representan la expresión (que es cómo los mapeadores de objetos LINQ hacen su magia "integrada en el lenguaje").

Las Lambdas en LISP también se pueden pasar a un operador de presupuesto y luego se pueden recorrer como una lista de listas. Algunas macros poderosas se hacen de esta manera.



4

Solo porque no puedo ver un ejemplo de C ++ 11 aquí, seguiré y publicaré este bonito ejemplo desde aquí . Después de buscar, es el ejemplo específico de lenguaje más claro que pude encontrar.

Hola Lambdas, versión 1.

template<typename F>

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

Hola, Lambdas, versión 2:

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

3

Tengo problemas para comprender las expresiones lambda porque trabajo en Visual FoxPro, que tiene sustitución de macros y las funciones ExecScript {} y Evaluate (), que parecen tener el mismo propósito.

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

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

Un beneficio definitivo para usar lambdas formales es (supongo) la verificación en tiempo de compilación: Fox no sabrá si escribe la cadena de texto anterior hasta que intente ejecutarla.

Esto también es útil para el código basado en datos: puede almacenar rutinas completas en campos memo en la base de datos y luego evaluarlas en tiempo de ejecución. Esto le permite ajustar parte de la aplicación sin tener acceso a la fuente. (Pero ese es otro tema por completo).


3

Para una persona sin antecedentes de comp-sci, ¿qué es una lambda en el mundo de la informática?

Lo ilustraré intuitivamente paso a paso en códigos python simples y legibles.

En resumen, una lambda es solo una función anónima e inline.

Comencemos por la tarea de entender lambdascomo un estudiante de primer año con antecedentes de aritmética básica.

El plan de asignación es 'el nombre = valor', ver:

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

'x', 'y' son nombres y 1, 'valor' son valores. Prueba una función en matemáticas

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

Informes de error,
no puede escribir una matemática directamente como código, 'n' debe definirse o asignarse a un valor.

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

Funciona ahora, ¿y si insiste en combinar las dos líneas seperarte en una sola? Ahi vienelambda

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

No se informaron errores.

Esta es una mirada a lambda , le permite escribir una función en una sola línea como lo hace en matemática directamente en la computadora.

Lo veremos luego.

Continuemos profundizando en la 'asignación'.

Como se ilustra arriba, el símbolo igual = funciona para datos simples (1 y 'valor') tipo y expresión simple (n ** 2 + 2 * n + 1).

Prueba esto:

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 declaraciones simples, hay 11 tipos de ellas en Python 7. Declaraciones simples: documentación de Python 3.6.3

¿Qué tal una declaración compuesta,

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

Viene defhabilítala para que funcione

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

Tada, analícelo, 'm' es el nombre, 'n ** 2 + 2 * n + 1' es el valor. :es una variante de '='.
Encuéntralo, aunque solo sea por comprensión, todo comienza a partir de una tarea y todo es una tarea.

Ahora regrese a lambda, tenemos una función llamada 'm'

Tratar:

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

Aquí hay dos nombres de 'm', la función mya tiene un nombre, duplicado.

Tiene un formato como:

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

No es una estrategia inteligente, por lo que los informes de errores

Tenemos que eliminar uno de ellos, establecer una función sin nombre.

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

Se llama 'función anónima'

En conclusión,

  1. lambda en una función en línea que le permite escribir una función en una línea recta como lo hace en matemáticas
  2. lambda es anónimo

Espero que esto ayude.


2

Es una función que no tiene nombre. Por ejemplo, en c # puede usar

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

para devolver los números que son mayores que 5.

number => number > 5

Es la parte lambda aquí. Representa una función que toma un parámetro (número) y devuelve un valor booleano (número> 5). El método GetMatchingItems utiliza esta lambda en todos los elementos de la colección y devuelve los elementos coincidentes.


2

En Javascript, por ejemplo, las funciones son tratados como el mismo tipo mixto como todo lo demás ( int, string, float,bool ). Como tal, puede crear funciones sobre la marcha, asignarlas a cosas y volver a llamarlas más tarde. Es útil, pero no es algo que quieras usar en exceso o confundirás a todos los que tengan que mantener tu código después de ti ...

Este es un código con el que estaba jugando para ver qué tan profundo es este agujero de conejo:

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]()()();

2

En el contexto de CS, una función lambda es un concepto matemático abstracto que aborda un problema de evaluación simbólica de expresiones matemáticas. En ese contexto, una función lambda es lo mismo que un término lambda .

Pero en lenguajes de programación es algo diferente. Es un código que se declara "en su lugar" y que se puede transmitir como un "ciudadano de primera clase". Este concepto parecía ser útil, ya que llegó a casi todos los lenguajes de programación modernos populares (vea las funciones lambda en todas partes ).


2

A Lambda Function, o a Small Anonymous Function, es un bloque de funcionalidad autónomo que puede pasarse y usarse en su código. Lambda tiene diferentes nombres en diferentes lenguajes de programación: Lambdaen Python y Kotlin , Closureen Swift o Blocken C y Objective-C . Aunque el significado de lambda es bastante similar para estos idiomas, a veces tiene ligeras distinciones.

Veamos cómo funciona Lambda (cierre) en Swift 4.2 con el método sorted (), desde la función normal hasta la expresión más corta:

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

1. Función normal

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


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

2. Expresión de cierre

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

3. Expresión de cierre en línea

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

4. Inferir tipo de contexto

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

5. Devoluciones implícitas de cierres de expresión única

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

6. Nombres de argumentos abreviados

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

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

7. Métodos del operador

reverseOrder = coffee.sorted(by: >)

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

Espero que esto ayude.


1

Yo también lo tengo. Lo he intentado en JS con este:

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

Agrega 2 a 4 y luego genera un resultado de 6. Sin embargo, a veces me resulta difícil de leer :(

También he hecho una interesante para cada función:

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 iterará una matriz y realizará una acción, en el caso de imprimir en la consola. Ahora también entiendo por qué los labmdas son poderosos.


1

En la programación de computadoras, lambda es un fragmento de código (declaración, expresión o un grupo de ellos) que toma algunos argumentos de una fuente externa. No siempre debe ser una función anónima: tenemos muchas formas de implementarlas.

Tenemos una separación clara entre expresiones, declaraciones y funciones, que los matemáticos no tienen.

La palabra "función" en la programación también es diferente: tenemos "función es una serie de pasos para hacer" (del latín "realizar"). En matemáticas es algo acerca de la correlación entre variables.

Los lenguajes funcionales intentan ser lo más similares posible a las fórmulas matemáticas, y sus palabras significan casi lo mismo. Pero en otros lenguajes de programación lo tenemos diferente.


0

La pregunta ha sido respondida completamente, no quiero entrar en detalles. Quiero compartir el uso al escribir cálculos numéricos en óxido.

Hay un ejemplo de una lambda (función anónima)

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

Cuando estaba escribiendo un módulo del método Newton-Raphson, se usaba como derivada de primer y segundo orden. (Si desea saber qué es el método Newton-Raphson, visite " https://en.wikipedia.org/wiki/Newton%27s_method ".

La salida como la siguiente

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

f=98.000000       df=20.000000

0

Imagine que tiene un restaurante con una opción de entrega y que tiene que hacer un pedido en menos de 30 minutos. El punto es que a los clientes generalmente no les importa si envían sus alimentos en bicicleta con un automóvil o descalzos, siempre y cuando mantengan la comida caliente y atada. Así que vamos a convertir este idioma a Javascript con funciones de transporte anónimas y definidas.

A continuación, definimos la forma de nuestra entrega, también definimos un nombre para una función:

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

¿Qué pasaría si usáramos las funciones flecha / lambda para lograr esta transferencia?

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

Usted ve que no hay diferencia para el cliente y no pierde el tiempo para pensar en cómo enviar alimentos. Solo envialo.

Por cierto, no recomiendo el kebap con coca cola, es por eso que los códigos superiores te darán errores. Que te diviertas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.