stringtranslate.com

Función anónima

En programación de computadoras , una función anónima ( función literal , abstracción lambda , función lambda , expresión lambda o bloque ) es una definición de función que no está vinculada a un identificador . Las funciones anónimas suelen ser argumentos que se pasan a funciones de orden superior o se utilizan para construir el resultado de una función de orden superior que necesita devolver una función. [1] Si la función solo se usa una vez, o un número limitado de veces, una función anónima puede ser sintácticamente más ligera que usar una función con nombre. Las funciones anónimas son omnipresentes en los lenguajes de programación funcionales y otros lenguajes con funciones de primera clase , donde cumplen el mismo rol para el tipo de función que los literales para otros tipos de datos .

Las funciones anónimas tienen su origen en el trabajo de Alonzo Church en su invención del cálculo lambda , en el que todas las funciones son anónimas, en 1936, antes que los ordenadores electrónicos. [2] En varios lenguajes de programación, las funciones anónimas se introducen utilizando la palabra clave lambda , y las funciones anónimas a menudo se denominan lambdas o abstracciones lambda. Las funciones anónimas han sido una característica de los lenguajes de programación desde Lisp en 1958, y un número creciente de lenguajes de programación modernos admiten funciones anónimas.

Nombres

Los nombres "abstracción lambda", "función lambda" y "expresión lambda" se refieren a la notación de abstracción de funciones en el cálculo lambda, donde la función habitual f ( x ) = M se escribiría x . M ) ( M es una expresión que usa x ). Compárese con la sintaxis de Python de .lambda x: M

El nombre "función de flecha " se refiere al símbolo matemático " se asigna a ", xM. Compárese con la sintaxis de JavaScript de . [3]x => M

Usos

Las funciones anónimas se pueden utilizar para contener funciones que no necesitan ser nombradas y posiblemente para uso a corto plazo. Algunos ejemplos notables incluyen cierres y curry .

El uso de funciones anónimas es una cuestión de estilo. Usarlos nunca es la única forma de resolver un problema; En cambio, cada función anónima podría definirse como una función con nombre y llamarse por su nombre. Algunos programadores utilizan funciones anónimas para encapsular código específico no reutilizable sin ensuciar el código con muchas pequeñas funciones normales de una sola línea.

En algunos lenguajes de programación, las funciones anónimas se implementan comúnmente para propósitos muy específicos, como vincular eventos a devoluciones de llamadas o crear instancias de la función para valores particulares, lo que puede ser más eficiente, más legible y menos propenso a errores que llamar a una función con nombre más genérico. .

Los siguientes ejemplos están escritos en Python 3.

Clasificación

Al intentar ordenar de una forma no estándar, puede resultar más fácil contener la lógica de clasificación como una función anónima en lugar de crear una función con nombre. La mayoría de los lenguajes proporcionan una función de clasificación genérica que implementa un algoritmo de clasificación que clasificará objetos arbitrarios. Esta función suele aceptar una función arbitraria que determina cómo comparar si dos elementos son iguales o si uno es mayor o menor que el otro.

Considere este código Python que ordena una lista de cadenas por longitud de la cadena:

>>>  a  =  [ 'casa' ,  'coche' ,  'bicicleta' ] >>>  a . ordenar ( clave = lambda  x :  len ( x )) >>>  a [ 'coche' ,  'bicicleta' ,  'casa' ]

La función anónima en este ejemplo es la expresión lambda:

lambda  x :  len ( x )

La función anónima acepta un argumento, xy devuelve la longitud de su argumento, que luego el sort()método utiliza como criterio para la clasificación.

La sintaxis básica de una función lambda en Python es

lambda  arg1 ,  arg2 ,  arg3 ,  ... :  < operación  en  los  argumentos  que devuelven  un  valor >

La expresión devuelta por la función lambda se puede asignar a una variable y usarse en el código en varios lugares.

>>>  agregar  =  lambda  a :  a  +  a >>>  agregar ( 20 ) 40

Otro ejemplo sería ordenar elementos en una lista por el nombre de su clase (en Python, todo tiene una clase):

>>>  a  =  [ 10 ,  'número' ,  11.2 ] >>>  a . ordenar ( clave = lambda  x :  x . __clase__ . __nombre__ ) >>>  a [ 11.2 ,  10 ,  'número' ]

Tenga en cuenta que 11.2tiene el nombre de clase " float", 10tiene el nombre de clase " int" y 'number'tiene el nombre de clase " str". El orden de clasificación es " float", " int" y luego " str".

Cierres

Los cierres son funciones evaluadas en un entorno que contiene variables vinculadas . El siguiente ejemplo vincula la variable "umbral" en una función anónima que compara la entrada con el umbral.

def  comp ( umbral ):  devolver  lambda  x :  x  <  umbral

Esto se puede utilizar como una especie de generador de funciones de comparación:

>>>  func_a  =  comp ( 10 ) >>>  func_b  =  comp ( 20 )>>>  imprimir ( func_a ( 5 ),  func_a ( 8 ),  func_a ( 13 ),  func_a ( 21 )) Verdadero  Verdadero  Falso  Falso>>>  imprimir ( func_b ( 5 ),  func_b ( 8 ),  func_b ( 13 ),  func_b ( 21 )) Verdadero  Verdadero  Verdadero  Falso

No sería práctico crear una función para cada función de comparación posible y puede resultar demasiado inconveniente mantener el umbral para su uso posterior. Independientemente del motivo por el que se utiliza un cierre, la función anónima es la entidad que contiene la funcionalidad que realiza la comparación.

Zurra

Currying es el proceso de cambiar una función para que, en lugar de tomar múltiples entradas, tome una sola entrada y devuelva una función que acepte la segunda entrada, y así sucesivamente. En este ejemplo, una función que realiza división por cualquier número entero se transforma en una que realiza división por un número entero establecido.

>>>  def  dividir ( x ,  y ): ...  devolver  x  /  y>>>  def  divisor ( d ): ...  return  lambda  x :  dividir ( x ,  d )>>>  mitad  =  divisor ( 2 ) >>>  tercero  =  divisor ( 3 )>>>  imprimir ( la mitad ( 32 ),  la tercera ( 32 )) 16.0  10.666666666666666>>>  imprimir ( la mitad ( 40 ),  la tercera ( 40 )) 20.0  13.333333333333334

Si bien el uso de funciones anónimas quizás no sea común con el curry, aún así se pueden usar. En el ejemplo anterior, la función divisor genera funciones con un divisor específico. Las funciones mitad y tercer cursan la función de división con un divisor fijo.

La función divisora ​​también forma un cierre al vincular la variable d.

Funciones de orden superior

Una función de orden superior es una función que toma una función como argumento o devuelve una como resultado. Esto se usa comúnmente para personalizar el comportamiento de una función definida genéricamente, a menudo una construcción de bucle o un esquema de recursividad. Las funciones anónimas son una forma conveniente de especificar dichos argumentos de función. Los siguientes ejemplos están en Python 3.

Mapa

La función de mapa realiza una llamada de función en cada elemento de una lista. El siguiente ejemplo eleva al cuadrado cada elemento de una matriz con una función anónima.

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  lista ( mapa ( lambda  x :  x * x ,  a )) [ 1 ,  4 ,  9 ,  16 ,  25 ,  36 ]

La función anónima acepta un argumento y lo multiplica por sí mismo (lo eleva al cuadrado). La forma anterior es desaconsejada por los creadores del lenguaje, quienes sostienen que la forma que se presenta a continuación tiene el mismo significado y está más alineada con la filosofía del lenguaje:

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  [ x * x  para  x  en  a ] [ 1 ,  4 ,  9 ,  16 ,  25 ,  36 ]

Filtrar

La función de filtro devuelve todos los elementos de una lista que evalúan True cuando se pasan a una función determinada.

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  lista ( filtro ( lambda  x :  x  %  2  ==  0 ,  a )) [ 2 ,  4 ,  6 ]

La función anónima comprueba si el argumento que se le pasa es par. Al igual que con el mapa, se considera más apropiado el siguiente formulario:

>>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ,  6 ] >>>  [ x  para  x  en  a  si  x  %  2  ==  0 ] [ 2 ,  4 ,  6 ]

Doblar

Una función de plegado se ejecuta sobre todos los elementos de una estructura (para listas generalmente de izquierda a derecha, un "pliegue izquierdo", llamado reduceen Python), acumulando un valor a medida que avanza. Esto se puede utilizar para combinar todos los elementos de una estructura en un solo valor, por ejemplo:

>>>  desde  functools  importar  reducir >>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ] >>>  reducir ( lambda  x , y :  x * y ,  a ) 120

Esto realiza

La función anónima aquí es la multiplicación de los dos argumentos.

El resultado de un pliegue no tiene por qué ser un valor. En cambio, tanto el mapa como el filtro se pueden crear usando plegar. En el mapa, el valor que se acumula es una nueva lista que contiene los resultados de aplicar una función a cada elemento de la lista original. En el filtro, el valor que se acumula es una nueva lista que contiene solo aquellos elementos que coinciden con la condición dada.

Lista de idiomas

La siguiente es una lista de lenguajes de programación que admiten funciones anónimas sin nombre de forma total, parcial o nula.

Esta tabla muestra algunas tendencias generales. Primero, los lenguajes que no admiten funciones anónimas ( C , Pascal , Object Pascal ) son todos lenguajes de tipo estático. Sin embargo, los lenguajes escritos estáticamente pueden admitir funciones anónimas. Por ejemplo, los lenguajes ML se escriben estáticamente e incluyen fundamentalmente funciones anónimas, y Delphi , un dialecto de Object Pascal , se ha ampliado para admitir funciones anónimas, al igual que C++ (según el estándar C++11 ). En segundo lugar, los lenguajes que tratan las funciones como funciones de primera clase ( Dylan , Haskell , JavaScript , Lisp , ML , Perl , Python , Ruby , Scheme ) generalmente tienen soporte de funciones anónimas para que las funciones se puedan definir y transmitir tan fácilmente como otros datos. tipos.

Ejemplos

Numerosos idiomas admiten funciones anónimas o algo similar.

APL

Solo algunos dialectos admiten funciones anónimas, ya sea como dfns , en estilo tácito o una combinación de ambos.

 f ​​{ × } Como dfn f 1 2 3 1 4 9 g × Como tren tácito de 3 ( horquilla ) g 1 2 3 1 4 9 h × Como función tácita derivada h 1 23 1 4 9                                  

C (extensión no estándar)

La función anónima no es compatible con el lenguaje de programación C estándar, pero sí con algunos dialectos de C, como GCC [53] y Clang .

CCG

La colección de compiladores GNU (GCC) admite funciones anónimas, mezcladas con funciones anidadas y expresiones de declaración. Tiene la forma:

( { tipo de retorno nombre_funciones_anónimas ( parámetros ) { cuerpo_función } nombre_funciones_anónimas ; } )          

El siguiente ejemplo funciona sólo con GCC. Debido a cómo se expanden las macros, l_bodyno pueden contener comas fuera de los paréntesis; GCC trata la coma como un delimitador entre argumentos macro. El argumento l_ret_typese puede eliminar si __typeof__está disponible; en el siguiente ejemplo, usar __typeof__on array devolvería testtype *, al que se le puede desreferenciar el valor real si es necesario.

#incluir <stdio.h> //* esta es la definición de la función anónima */ #define lambda(l_ret_type, l_arguments, l_body) \  ({ \  l_ret_type l_anonymous_functions_name l_arguments \  l_body \  &l_anonymous_functions_name; \  })#define forEachInArray(fe_arrType, fe_arr, fe_fn_body) \ { \  int i=0; \  for(;i<tamañode(fe_arr)/tamañode(fe_arrType);i++) { fe_arr[i] = fe_fn_body(&fe_arr[i]); } \ }estructura typedef { int a ; intb ;} tipo de prueba ;      impresión nula ( const tipo de prueba * matriz ) { int i ; for ( i = 0 ; i < 3 ; ++ i ) printf ( "%d %d \n " , matriz [ i ]. a , matriz [ i ]. b ); printf ( " \n " ); }                     int main ( void ) { matriz de tipo de prueba [] = { { 0 , 1 }, { 2 , 3 }, { 4 , 5 } };          impresión ( matriz ); /* la función anónima se proporciona como función para foreach */ forEachInArray ( testtype , array , lambda ( testtype , ( void * item ), { int temp = ( * ( testtype * ) item ). a ; ( * ( testtype * ) elemento ). a = ( * ( tipo de prueba * ) elemento ). b ; ( * ( tipo de prueba * ) elemento ). b = temp ; return ( * ( tipo de prueba * ) elemento ); })); impresión ( matriz ); devolver 0 ; }                                       

Sonido metálico (C, C++, Objective-C, Objective-C++)

Clang admite funciones anónimas, llamadas bloques , [54] que tienen la forma:

^ tipo_retorno ( parámetros ) { cuerpo_función }      

El tipo de los bloques anteriores es return_type (^)(parameters).

Usando la extensión de bloques antes mencionada y Grand Central Dispatch (libdispatch), el código podría verse más simple:

#incluir <stdio.h> #incluir <despacho/despacho.h>  int main ( void ) { void ( ^ count_loop )() = ^ { for ( int i = 0 ; i < 100 ; i ++ ) printf ( "%d \n " , i ); printf ( "ah ah ah \n " ); };                   /* Pasar como parámetro a otra función */ despacho_async ( despacho_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 ), count_loop );   /* Invocar directamente */ count_loop ();  devolver 0 ; } 

El código con bloques debe compilarse -fblocksy vincularse con-lBlocksRuntime

C++ (desde C++11)

C++ 11 admite funciones anónimas (técnicamente objetos de función ), llamadas expresiones lambda , [55] que tienen la forma:

[ capturas ] ( parámetros ) las especificaciones requieren ( opcional ) { cuerpo }          

donde " specs" tiene la forma " en ese orden; cada uno de estos componentes es opcional". Si está ausente, el tipo de retorno se deduce de las declaraciones como si fuera una función con el tipo de retorno declarado .specifiers exception attr trailing-return-typereturnauto

Este es un ejemplo de expresión lambda:

[]( int x , int y ) { retorno x + y ; }         

C++ 11 también admite cierres , aquí llamados capturas. Las capturas se definen entre corchetes [y ]en la declaración de expresión lambda. El mecanismo permite capturar estas variables por valor o por referencia. La siguiente tabla demuestra esto:

[] // Sin capturas, la lambda se puede convertir implícitamente en un puntero de función. [ x , & y ] // x se captura por valor y y se captura por referencia. [ & ] // Cualquier variable externa se captura implícitamente por referencia si se usa [ = ] // Cualquier variable externa se captura implícitamente por valor si se usa. [ & , x ] // x se captura por valor. Otras variables se capturarán por referencia. [ = , & z ] // z se captura por referencia. Otras variables serán capturadas por valor.         

Las variables capturadas por valor son constantes de forma predeterminada. Agregar mutabledespués de la lista de parámetros los hace no constantes.

C++14 y versiones más recientes admiten init-capture, por ejemplo:

std :: only_ptr < int > ptr = std :: make_unique < int > ( 42 ); [ ptr ]{ /* ... */ }; // la asignación de copia se elimina para un puntero único [ ptr = std :: move ( ptr )]{ /* ... */ }; // OK           contador automático = [ i = 0 ]() mutable { retorno i ++ ; }; // se requiere mutable para modificar el contador 'i' (); // 0 contador (); // 1 contador (); // 2              

Los dos ejemplos siguientes demuestran el uso de una expresión lambda:

std :: vector < int > alguna_lista { 1 , 2 , 3 , 4 , 5 }; entero total = 0 ; std :: for_each ( comenzar ( alguna lista ), finalizar ( alguna lista ), [ & total ] ( int x ) { total += x ; }); // Tenga en cuenta que std::accumulate sería una alternativa mucho mejor aquí...                   

Esto calcula el total de todos los elementos de la lista. La variable totalse almacena como parte del cierre de la función lambda. Dado que es una referencia a la variable de pila total, puede cambiar su valor.

std :: vector < int > alguna_lista { 1 , 2 , 3 , 4 , 5 }; entero total = 0 ; valor entero = 5 ; std :: for_each ( comenzar ( alguna lista ), finalizar ( alguna lista ), [ & total , valor , esto ] ( int x ) { total += x * valor * esto -> alguna_func (); });                            

Esto hará que totalse almacene como referencia, pero valuese almacenará como una copia.

La captura de thises especial. Sólo puede capturarse por valor, no por referencia. Sin embargo, en C++17 , el objeto actual puede capturarse por valor (indicado por *this) o puede capturarse por referencia (indicado por this). thissolo se puede capturar si la función envolvente más cercana es una función miembro no estática. La lambda tendrá el mismo acceso que el miembro que la creó, en términos de miembros protegidos/privados.

Si thisse captura, ya sea explícita o implícitamente, también se prueba el alcance de los miembros de la clase adjunta. Acceder a miembros de thisno necesita el uso explícito de this->sintaxis.

La implementación interna específica puede variar, pero la expectativa es que una función lambda que captura todo por referencia almacene el puntero de pila real de la función en la que se crea, en lugar de referencias individuales a variables de pila. Sin embargo, debido a que la mayoría de las funciones lambda son pequeñas y de alcance local, es probable que sean candidatas para inlining y, por lo tanto, no necesitan almacenamiento adicional para las referencias.

Si se invoca un objeto de cierre que contiene referencias a variables locales después del alcance del bloque más interno de su creación, el comportamiento no está definido .

Las funciones Lambda son objetos de función de un tipo dependiente de la implementación; El nombre de este tipo sólo está disponible para el compilador. Si el usuario desea tomar una función lambda como parámetro, el tipo de parámetro debe ser un tipo de plantilla o debe crear un std::functionobjeto similar para capturar el valor lambda. El uso de autopalabras clave puede ayudar a almacenar la función lambda,

auto my_lambda_func = [ & ]( int x ) { /*...*/ }; auto my_onheap_lambda_func = nuevo auto ([ = ]( int x ) { /*...*/ });               

A continuación se muestra un ejemplo de almacenamiento de funciones anónimas en variables, vectores y matrices; y pasándolos como parámetros con nombre:

#include <funcional> #include <iostream> #include <vector>   doble evaluación ( std :: función < doble ( doble ) > f , doble x = 2.0 ) { retorno f ( x ); }         int main () { std :: función < doble ( doble ) > f0 = []( doble x ) { retorno 1 ; }; auto f1 = []( doble x ) { retorno x ; }; decltype ( f0 ) fa [ 3 ] = { f0 , f1 , []( doble x ) { return x * x ; }}; std :: vector < decltype ( f0 ) > fv = { f0 , f1 }; fv . push_back ([]( doble x ) { retorno x * x ; }); for ( size_t i = 0 ; i < fv . size (); i ++ ) { std :: cout << fv [ i ]( 2.0 ) << std :: endl ; } for ( size_t i = 0 ; i < 3 ; i ++ ) { std :: cout << fa [ i ]( 2.0 ) << std :: endl ; } for ( auto & f : fv ) { std :: cout << f ( 2.0 ) << std :: endl ; } para ( auto & f : fa ) { std :: cout << f ( 2.0 ) << std ::                                                                                                     fin ; } std :: cout << eval ( f0 ) << std :: endl ; std :: cout << eval ( f1 ) << std :: endl ; std :: cout << eval ([]( doble x ) { return x * x ; }) << std :: endl ; }                       

Una expresión lambda con una especificación de captura vacía ( []) se puede convertir implícitamente en un puntero de función con el mismo tipo con el que se declaró la lambda. Entonces esto es legal:

auto a_lambda_func = []( int x ) -> void { /*...*/ }; vacío ( * func_ptr ) ( int ) = a_lambda_func ; func_ptr ( 4 ); //llama a lambda.              

Desde C++17 , se puede declarar una lambda constexpr, y desde C++20 , constevalcon la semántica habitual. Estos especificadores van después de la lista de parámetros, como mutable. A partir de C++23 , la lambda también puede serlo staticsi no tiene capturas. No se permite combinar los especificadores staticy .mutable

Además, desde C++ 23, una expresión lambda puede ser recursiva a través de thisun primer parámetro explícito:

auto fibonacci = []( este auto self , int n ) { return n <= 1 ? n : yo ( n - 1 ) + yo ( n - 2 ); }; fibonacci ( 7 ); // 13                        

Además de eso, C++23 modificó la sintaxis para que los paréntesis se puedan omitir en el caso de una lambda que no acepta argumentos incluso si la lambda tiene un especificador. También hizo que una secuencia de especificador de atributos que aparece antes de la lista de parámetros, los especificadores lambda o el especificador noexcept (debe haber uno de ellos) se aplique al operador de llamada de función o a la plantilla de operador del tipo de cierre. De lo contrario, se aplica al tipo de operador de llamada de función o plantilla de operador. Anteriormente, dicha secuencia siempre se aplicaba al tipo de operador de llamada de función o plantilla de operador del tipo de cierre, lo que hacía, por ejemplo, que el [[noreturn]]atributo fuera imposible de usar con lambdas.

La biblioteca Boost también proporciona su propia sintaxis para funciones lambda, utilizando la siguiente sintaxis: [56]

for_each ( a . comenzar (), a . fin (), std :: cout << _1 << ' ' );      

Desde C++ 14 , los parámetros de función de una lambda se pueden declarar con auto. La lambda resultante se denomina lambda genérica y es esencialmente una plantilla de función anónima, ya que las reglas para la deducción de tipos de los parámetros automáticos son las reglas de deducción de argumentos de plantilla. A partir de C++20 , los parámetros de plantilla también se pueden declarar explícitamente con la siguiente sintaxis:

[ capturas ] <tparams> requiere ( opcional ) ( params ) las especificaciones requieren ( opcional ) { cuerpo }              

C#

En C# , la compatibilidad con funciones anónimas se ha profundizado a través de las distintas versiones del compilador del lenguaje. El lenguaje v3.0, lanzado en noviembre de 2007 con .NET Framework v3.5, tiene soporte completo para funciones anónimas. [57] : 7–8  [58] : 26  C# las denomina expresiones lambda , siguiendo la versión original de funciones anónimas, el cálculo lambda . [59] [57] : 7–8, 91  [58] : 91 

// el primer int es el tipo x' // el segundo int es el tipo de retorno // <see href="http://msdn.microsoft.com/en-us/library/bb549151.aspx" />Func<int,int> foo = x => x * x;Console.WriteLine(foo(7));

Si bien la función es anónima, no se puede asignar a una variable escrita implícitamente, porque la sintaxis lambda se puede usar para indicar una función anónima o un árbol de expresión, y el compilador no puede decidir automáticamente la elección. [57] : 101–103  Por ejemplo, esto no funciona:

// ¡NO se compilará! var foo = ( int x ) => x * x ;        

Sin embargo, una expresión lambda puede participar en la inferencia de tipos y puede usarse como argumento de método , por ejemplo, para usar funciones anónimas con la capacidad Map disponible con System.Collections.Generic.List(en el ConvertAll()método):

// Inicializa la lista: var valores = nueva Lista < int > () { 7 , 13 , 4 , 9 , 3 }; // Asigna la función anónima a todos los elementos de la lista, devuelve la nueva lista var foo = valores . ConvertirTodo ( d => d * d ) ; // el resultado de la variable foo es de tipo System.Collections.Generic.List<Int32>                    

Las versiones anteriores de C# tenían un soporte más limitado para funciones anónimas. C# v1.0, introducido en febrero de 2002 con .NET Framework v1.0, proporcionó soporte parcial para funciones anónimas mediante el uso de delegados . [57] : 6  C# las denomina expresiones lambda , siguiendo la versión original de funciones anónimas, el cálculo lambda . [57] : 91  Esta construcción es algo similar a los delegados de PHP. En C# 1.0, los delegados son como punteros de función que hacen referencia a un método nombrado explícitamente dentro de una clase. (Pero a diferencia de PHP, el nombre no es necesario en el momento en que se utiliza el delegado). C# v2.0, lanzado en noviembre de 2005 con .NET Framework v2.0, introdujo el concepto de métodos anónimos como una forma de escribir declaraciones en línea sin nombre. bloques que se pueden ejecutar en una invocación de delegado. [57] : 6–7  C# 3.0 continúa admitiendo estas construcciones, pero también admite la construcción de expresión lambda.

Este ejemplo se compilará en C# 3.0 y exhibirá las tres formas:

 clase pública TestDriver { delegado int SquareDelegate ( int d ); estático int cuadrado ( int d ) { return d * d ; } static void Main ( string [] args ) { // C# 1.0: se necesita la sintaxis delegada original // inicializando con un método con nombre. SquareDelegate A = nuevo SquareDelegate ( Cuadrado ); Sistema . Consola . Línea de escritura ( A ( 3 )); // C# 2.0: un delegado se puede inicializar con // código en línea, llamado "método anónimo". Este // método toma un int como parámetro de entrada. SquareDelegate B = delegado ( int d ) { return d * d ; }; Sistema . Consola . Línea de escritura ( B ( 5 )); // C# 3.0. Un delegado se puede inicializar con // una expresión lambda. La lambda toma un int y devuelve un int. // El compilador infiere el tipo de x. Delegado cuadrado C = x => x * x ; Sistema . Consola . Línea de escritura ( C ( 7 )); // C# 3.0. Un delegado que acepta una entrada y // devuelve una salida también se puede declarar implícitamente con el tipo Func<>. Sistema . Func < int , int > D = x => x * x ; Sistema . Consola . Línea de escritura ( D ( 9 )); } }                                                                           

En el caso de la versión C# 2.0, el compilador de C# toma el bloque de código de la función anónima y crea una función privada estática. Internamente, la función obtiene un nombre generado, por supuesto; este nombre generado se basa en el nombre del método en el que se declara el Delegado. Pero el nombre no está expuesto al código de la aplicación excepto mediante el uso de reflexión . [57] : 103  En el caso de la versión C# 3.0 se aplica el mismo mecanismo.

Lenguaje de marcado ColdFusion (CFML)

Utilizando elfunciónpalabra clave:

fn  =  función (){  // declaraciones };

O usando una función de flecha:

fn  =  ()  =>  {  // declaraciones };fn  =  ()  =>  singleExpression  // singleExpression se devuelve implícitamente. No son necesarias las llaves ni la palabra clave return.fn  =  singleParam  =>  {  // si la función de flecha tiene solo un parámetro, no hay necesidad de paréntesis  // declaraciones }fn  =  ( x ,  y )  =>  {  // si la función de flecha tiene cero o múltiples parámetros, es necesario usar paréntesis  // declaraciones }

CFML admite cualquier declaración dentro de la definición de la función, no simplemente expresiones.

CFML admite funciones anónimas recursivas:

factorial  =  función ( n ){  retorno  n  >  1  ?  n  *  factorial ( n - 1 )  :  1 ; };

Las funciones anónimas de CFML implementan el cierre.

D

D utiliza delegados en línea para implementar funciones anónimas. La sintaxis completa para un delegado en línea es

return_type delegado ( argumentos ){ /*cuerpo*/ } 

Si no es ambiguo, se pueden omitir el tipo de retorno y la palabra clave delegado .

( x ){ return x * x ;} delegado ( x ){ return x * x ;} // si se necesita más detalle ( int x ){ return x * x ;} // si no se puede inferir el tipo de parámetro delegado ( int x ){ return x * x ;} // lo mismo delegar double ( int x ){ return x * x ;} // si el tipo de retorno debe forzarse manualmente               

Desde la versión 2.0, D asigna cierres en el montón a menos que el compilador pueda demostrar que es innecesario; la scopepalabra clave se puede utilizar para forzar la asignación de la pila. Desde la versión 2.058, es posible utilizar notación abreviada:

x => x * x ; ( int x ) => x * x ; ( x , y ) => x * y ; ( int x , int y ) => x * y ;            

Se puede asignar una función anónima a una variable y usarla así:

auto sqr = ( doble x ){ retorno x * x ;}; doble y = sqr ( 4 );        

Dardo

Dart admite funciones anónimas. [11]

var sqr = ( x ) => x * x ; imprimir ( sqr ( 5 ));       

o

imprimir ((( x ) => x * x )( 5 ));    

Delfos

Delphi introdujo funciones anónimas en la versión 2009.

demostración del programa ; escriba TSimpleProcedure = referencia al procedimiento ; TSimpleFunction = referencia a la función ( const x : cadena ) : entero ;             var x1 : TProcedimientoSimple ; y1 : TFunciónSimple ;    comenzar x1 : = procedimiento comenzar Writeln ( 'Hola mundo' ) ; fin ; x1 ; //invocar el método anónimo recién definido         y1 : = función ( const x : cadena ) : entero comienzo Resultado : = Longitud ( x ) ; fin ; Writeln ( y1 ( 'barra' )) ; fin .            

PascalABC.NET

PascalABC.NET admite funciones anónimas utilizando sintaxis lambda

comenzar var n : = 10000000 ; var pp := ( 1 .. n ) . Seleccione ( x -> ( Aleatorio , Aleatorio )) . Donde ( p -> Cuadrado ( p [ 0 ]) + Cuadrado ( p [ 1 ]) < 1 ) . Contar / n * 4 ; Imprimir ( páginas ) ; fin .                         

Elixir

Elixir utiliza el cierre fn para funciones anónimas. [15]

suma = fn ( a , b ) -> a + b suma final . ( 4 , 3 ) #=> 7         cuadrado = fn ( x ) -> x * x end Enum . mapa [ 1 , 2 , 3 , 4 ], cuadrado #=> [1, 4, 9, 16]            

erlang

Erlang utiliza una sintaxis para funciones anónimas similar a la de las funciones con nombre. [dieciséis]

% Función anónima vinculada a la variable Square Square = fun ( X ) -> X * X end .       % Función nombrada con la misma funcionalidad cuadrado ( X ) -> X * X .    

Ir

Go admite funciones anónimas. [21]

foo := func ( x int ) int { return x * x } fmt . Imprimir ( foo ( 10 ))        

Haskell

Haskell utiliza una sintaxis concisa para funciones anónimas (expresiones lambda). Se supone que la barra invertida se parece a λ.

\ x- > x * x    

Las expresiones Lambda están completamente integradas con el motor de inferencia de tipos y admiten toda la sintaxis y características de las funciones "ordinarias" (excepto el uso de múltiples definiciones para la coincidencia de patrones, ya que la lista de argumentos solo se especifica una vez).

mapa ( \ x -> x * x ) [ 1 .. 5 ] - devuelve [1, 4, 9, 16, 25]       

Los siguientes son todos equivalentes:

f x y = x + y f x = \ y -> x + y f = \ x y -> x + y                    

Hax

En Haxe , las funciones anónimas se denominan lambda y utilizan la sintaxis function(argument-list) expression;.

var f = función ( x ) return x * x ; f ( 8 ); // 64      ( función ( x , y ) devuelve x + y )( 5 , 6 ); // 11   

Java

Java admite funciones anónimas, denominadas Lambda Expressions , a partir de JDK 8 . [60]

Una expresión lambda consta de una lista separada por comas de parámetros formales entre paréntesis, un símbolo de flecha ( ->) y un cuerpo. Los tipos de datos de los parámetros siempre se pueden omitir, al igual que los paréntesis si solo hay un parámetro. El cuerpo puede constar de una declaración o un bloque de declaraciones. [61]

// sin parámetro () -> Sistema . afuera . println ( "Hola mundo." )  // con un parámetro (este ejemplo es una función de identidad). un -> un  // con una expresión ( a , b ) -> a + b     // con información de tipo explícita ( id larga , nombre de cadena ) -> "id: " + id + ", nombre:" + nombre           // con un bloque de código ( a , b ) -> { return a + b ; }        // con múltiples declaraciones en el cuerpo lambda. Necesita un bloque de código. // Este ejemplo también incluye dos expresiones lambda anidadas (la primera también es un cierre). ( id , PrecioPredeterminado ) - > { Opcional <Producto> producto = ListaProductos .arroyo (). filtrar ( p -> p . getId () == id ). encontrarPrimero (); devolver el producto . mapa ( p -> p . getPrice ()). o si no ( precio predeterminado ); }               

Las expresiones Lambda se convierten en "interfaces funcionales" (definidas como interfaces que contienen solo un método abstracto además de uno o más métodos predeterminados o estáticos), [61] como en el siguiente ejemplo:

Calculadora de clase pública { interfaz IntegerMath { int operación ( int a , int b );            intercambio predeterminado de IntegerMath () { retorno ( a , b ) -> operación ( b , a ); } }            aplicación int estática privada ( int a , int b , operación IntegerMath ) { retorno op . operación ( a , b ); }              public static void main ( String ... args ) { suma IntegerMath = ( a , b ) -> a + b ; Resta de enteros matemáticos = ( a , b ) -> a - b ; Sistema . afuera . println ( "40 + 2 = " + aplicar ( 40 , 2 , suma )); Sistema . afuera . println ( "20 - 10 = " + aplicar ( 20 , 10 , resta )); Sistema . afuera . println ( "10 - 20 = " + aplicar ( 20 , 10 , resta . swap ())); } }                                        

En este ejemplo, IntegerMathse declara una interfaz funcional llamada. Las expresiones lambda que se implementan IntegerMathse pasan al apply()método que se va a ejecutar. Métodos predeterminados como swapmétodos de definición de funciones.

Java 8 introdujo otro mecanismo llamado referencia de método (el ::operador) para crear una lambda en un método existente. Una referencia de método no indica el número o los tipos de argumentos porque se extraen del método abstracto de la interfaz funcional.

IntBinaryOperator suma = Entero :: suma ;   

En el ejemplo anterior, la interfaz funcional IntBinaryOperatordeclara un método abstracto int applyAsInt(int, int), por lo que el compilador busca un método int sum(int, int)en la clase java.lang.Integer.

Diferencias con las clases anónimas

Las clases anónimas de interfaces compatibles con lambda son similares, pero no exactamente equivalentes, a las expresiones lambda. Para ilustrar, en el siguiente ejemplo, anonymousClassy lambdaExpressionson ambas instancias de IntegerMathlas que suman sus dos parámetros:

IntegerMath anonymClass = new IntegerMath () { @Override operación int pública ( int a , int b ) { return a + b ; } }; IntegerMath expresión lambda = ( a , b ) -> a + b ;                          

La principal diferencia aquí es que la expresión lambda no necesariamente necesita asignar una nueva instancia para IntegerMathy puede devolver la misma instancia cada vez que se ejecuta este código. [62] Además, al menos en la implementación de OpenJDK , las lambdas se compilan para invocar instrucciones dinámicas , con el cuerpo lambda insertado como un método estático en la clase circundante, [63] en lugar de generar un nuevo archivo de clase por completo.

Limitaciones de Java

Las lambdas de Java 8 tienen las siguientes limitaciones:

javascript

JavaScript / ECMAScript admite funciones anónimas.

alerta (( función ( x ) { retorno x * x ; })( 10 ));    

ES6 admite la sintaxis de "función de flecha", donde un símbolo => separa la lista de parámetros de la función anónima del cuerpo:

alerta (( x => x * x )( 10 ));    

Esta construcción se utiliza a menudo en Bookmarklets . Por ejemplo, para cambiar el título del documento actual (visible en la barra de título de su ventana ) a su URL , el siguiente bookmarklet puede parecer que funciona.

documento . título = ubicación . href ;

Sin embargo, como la declaración de asignación devuelve un valor (la propia URL), muchos navegadores crean una nueva página para mostrar este valor.

En su lugar, se puede utilizar una función anónima, que no devuelve un valor:

( función (){ documento . título = ubicación . href ;})();

La declaración de función en el primer par de paréntesis (exterior) declara una función anónima, que luego se ejecuta cuando se usa con el último par de paréntesis. Esto es casi equivalente a lo siguiente, que llena el entorno con funa función anónima diferente.

var f = función (){ documento . título = ubicación . href ;}; f ();    

Utilice void() para evitar nuevas páginas para funciones anónimas arbitrarias:

void ( función (){ devolver documento . título = ubicación . href ;}()); 

o solo:

vacío ( documento . título = ubicación . href );

JavaScript tiene sutilezas sintácticas para la semántica de definir, invocar y evaluar funciones anónimas. Estos matices subliminales son consecuencia directa de la evaluación de expresiones entre paréntesis. Las siguientes construcciones que se denominan expresión de función de invocación inmediata ilustran esto:

( función (){ ... }())  

y

( función (){ ... })()  

Al representar " function(){ ... }" por f, la forma de las construcciones son un paréntesis dentro de un paréntesis (f())y un paréntesis aplicado a un paréntesis (f)().

Tenga en cuenta la ambigüedad sintáctica general de una expresión entre paréntesis, los argumentos entre paréntesis de una función y los paréntesis alrededor de los parámetros formales en una definición de función. En particular, JavaScript define un ,operador (coma) en el contexto de una expresión entre paréntesis. ¡No es mera coincidencia que las formas sintácticas coincidan para una expresión y los argumentos de una función (ignorando la sintaxis formal de los parámetros de la función)! Si fno se identifica en las construcciones anteriores, se convierten en (())y ()(). El primero no proporciona ninguna pista sintáctica de ninguna función residente, pero el segundo DEBE evaluar el primer paréntesis como una función para que sea JavaScript legal. (Aparte: por ejemplo, el ()'s podría ser ([],{},42,"abc",function(){}) siempre que la expresión se evalúe como una función).

Además, una función es una instancia de Objeto (de la misma manera, los objetos son instancias de Función) y los corchetes de notación literal de objeto, {}para código entre llaves, se usan al definir una función de esta manera (en lugar de usar new Function(...)). En un sentido muy amplio y no riguroso (especialmente porque los enlaces globales están comprometidos), una secuencia arbitraria de declaraciones JavaScript arriostradas, {stuff}puede considerarse como un punto fijo de

( función (){( función (){( ... {( función (){ cosas }() )} ... )}() )}() )         

Más correctamente pero con salvedades,

( función (){ cosas }() ) ~= A_Fixed_Point_of ( función (){ función de retorno (){ retorno ... { función de retorno (){ cosas }() } ... }() }() )                 

Tenga en cuenta las implicaciones de la función anónima en los fragmentos de JavaScript que siguen:

Las métricas de rendimiento para analizar las complejidades espaciales y temporales de las llamadas a funciones, la pila de llamadas, etc. en un motor de interpretación de JavaScript se implementan fácilmente con estas últimas construcciones de funciones anónimas. A partir de las implicaciones de los resultados, es posible deducir algunos de los detalles de implementación recursiva versus iterativa de un motor, especialmente la recursividad de cola .

Julia

En Julia, las funciones anónimas se definen utilizando la sintaxis (arguments)->(expression),

julia> f = x- > x * x ; f ( 8 ) 64 julia> (( x , y ) -> x + y )( 5 , 6 ) 11       

Kotlin

Kotlin admite funciones anónimas con la sintaxis {arguments -> expression},

val suma = { x : Int , y : Int -> x + y } suma ( 5 , 6 ) // devuelve 11 val par = { x : Int -> x % 2 == 0 } par ( 4 ) // devuelve verdadero                     

Ceceo

Lisp y Scheme admiten funciones anónimas utilizando la construcción "lambda", que es una referencia al cálculo lambda . Clojure admite funciones anónimas con la forma especial "fn" y la sintaxis del lector #().

( lambda ( arg ) ( * arg arg ))    

ceceo común

Common Lisp tiene el concepto de expresiones lambda. Una expresión lambda se escribe como una lista con el símbolo "lambda" como primer elemento. Luego, la lista contiene la lista de argumentos, documentación o declaraciones y el cuerpo de la función. Las expresiones lambda se pueden utilizar dentro de formularios lambda y con el operador especial "función".

( función ( lambda ( arg ) ( hacer algo arg )))    

"función" se puede abreviar como #'. Además, existe una macro lambda , que se expande a una forma de función:

; usando comillas marcadas #' ( lambda ( arg ) ( hacer algo arg )) ; usando la macro lambda: ( lambda ( arg ) ( hacer algo arg ))      

Un uso típico de funciones anónimas en Common Lisp es pasarlas a funciones de orden superior como mapcar , que aplica una función a cada elemento de una lista y devuelve una lista de resultados.

( mapcar #' ( lambda ( x ) ( * x x )) ' ( 1 2 3 4 )) ; -> (1 4 9 16)         

La forma lambda en Common Lisp permite escribir una expresión lambda en una llamada de función:

(( lambda ( x y ) ( + ( raíz cuadrada x ) ( raíz cuadrada y ))) 10,0 12,0 )         

A las funciones anónimas en Common Lisp también se les pueden dar nombres globales:

( setf ( símbolo-función 'sqr ) ( lambda ( x ) ( * x x ))) ; lo que nos permite llamarlo usando el nombre SQR: ( sqr 10.0 )        

Esquema

Las funciones con nombre de Scheme son simplemente azúcar sintáctico para funciones anónimas vinculadas a nombres:

( definir ( algún nombre arg ) ( hacer algo arg ))    

se expande (y es equivalente) a

( define algún nombre ( lambda ( arg ) ( hacer algo arg )))     

Clojure

Clojure admite funciones anónimas a través de la forma especial "fn":

( fn [x] ( + x 3 ))    

También hay una sintaxis de lector para definir una lambda:

#( + % %2%3 ) ; Define una función anónima que toma tres argumentos y los suma.   

Al igual que Scheme, las "funciones con nombre" de Clojure son simplemente azúcar sintáctico para lambdas vinculadas a nombres:

( definición de función [arg] ( + 3 arg ))     

se expande a:

( def func ( fn [arg] ( + 3 arg )))      

lua

En Lua (al igual que en Scheme) todas las funciones son anónimas. Una función con nombre en Lua es simplemente una variable que contiene una referencia a un objeto de función. [64]

Así, en Lua

función  foo ( x )  retorno  2 * x  final

es solo azúcar sintáctico para

foo  =  función ( x )  retorno  2 * x  final

Un ejemplo del uso de funciones anónimas para la clasificación en orden inverso:

table.sort ( red ,  función ( a , b )  devuelve  a . nombre  >  b . nombre final )

Wolfram Language, Matemática

Wolfram Language es el lenguaje de programación de Mathematica . Las funciones anónimas son importantes en la programación de este último. Hay varias formas de crearlos. A continuación se muestran algunas funciones anónimas que incrementan un número. El primero es el más común. #1se refiere al primer argumento y &marca el final de la función anónima.

 #1 + 1 & Función [ x , x + 1 ] x \ [ Función ] x + 1    

Así, por ejemplo:

 f := #1 ^ 2 & ; f [ 8 ] 64 #1 + #2 y [ 5 , 6 ] 11    

Además, Mathematica tiene una construcción adicional para realizar funciones anónimas recursivas. El símbolo '#0' se refiere a la función completa. La siguiente función calcula el factorial de su entrada:

 Si [ #1 == 1 , 1 , #1 * #0 [ #1 -1 ]] &      

Por ejemplo, 6 factorial sería:

 Si [ #1 == 1 , 1 , #1 * #0 [ #1 -1 ]] y [ 6 ] 720      

MATLAB, octava

Las funciones anónimas en MATLAB u Octave se definen mediante la sintaxis @(argument-list)expression. Cualquier variable que no se encuentre en la lista de argumentos se hereda del ámbito adjunto y se captura por valor.

>> f = @( x ) x * x ; f ( 8 ) ans = 64 >> (@( x , y ) x + y )( 5 , 6 ) % Solo funciona en Octava ans = 11          

máxima

En Maxima las funciones anónimas se definen usando la sintaxis lambda(argument-list,expression),

f : lambda ([ x ], x * x ); f ( 8 );   64lambda ([ x , y ], x + y )( 5 , 6 ); 11

ml

Los distintos dialectos de ML admiten funciones anónimas.

OCaml

Las funciones anónimas en OCaml son funciones sin un nombre declarado. A continuación se muestra un ejemplo de una función anónima que multiplica su entrada por dos:

divertido  x  ->  x * 2

En el ejemplo, diversión es una palabra clave que indica que la función es anónima. Pasamos un argumento x y -> para separar el argumento del cuerpo. [sesenta y cinco]

F#

F# admite funciones anónimas, [17] de la siguiente manera:

( divertido x -> x * x ) 20 // 400       

AA estándar

El ML estándar admite funciones anónimas, de la siguiente manera:

fn arg => arg * arg

nim

Nim admite funciones anónimas de múltiples expresiones y líneas múltiples. [33]

var anon = proc ( var1 , var2 : int ): int = var1 + var2 afirmar anon ( 1 , 2 ) == 3               

Ejemplo de varias líneas:

var anon = func ( x : int ): bool = si x > 0 : resultado = verdadero de lo contrario : resultado = falso                   afirmar anon ( 9 ) 

Se pueden pasar funciones anónimas como parámetros de entrada de otras funciones:

var ciudades = @[ "Frankfurt" , "Tokio" , "Nueva York" ]     ciudades . ordenar ( proc ( x , y : cadena ): int = cmp ( x . len , y . len ) )        

Una función anónima es básicamente una función sin nombre.

perla

perla 5

Perl 5 admite funciones anónimas, [37] de la siguiente manera:

( sub { print "Me llamaron\n" }) -> (); # 1. totalmente anónimo, llamado tal como se creó     mi $cuadrado = sub { mi $x = cambio ; $x * $x }; # 2. asignado a una variable             sub curry { mi ( $sub , @args ) = @_ ; devolver sub { $sub -> ( @args , @_ ) }; # 3. como valor de retorno de otra función }              # ejemplo de curry en programación Perl sub sum { my $tot = 0 ; $tot += $_ para @_ ; $tot } # devuelve la suma de sus argumentos my $curried = curry \& sum , 5 , 7 , 9 ; imprimir $curry -> ( 1 , 2 , 3 ), "\n" ; # imprime 27 ( = 5 + 7 + 9 + 1 + 2 + 3 )                        

Otras construcciones toman bloques desnudos como argumentos, que cumplen una función similar a las funciones lambda de un parámetro, pero no tienen la misma convención de paso de parámetros que las funciones: @_ no está configurado.

mis @cuadrados = mapa { $_ * $_ } 1 .. 10 ; # map y grep no usan la palabra clave 'sub' my @square2 = map $_ * $_ , 1 .. 10 ; # llaves innecesarias para una expresión                  mi @bad_example = mapa { imprimir para @_ } 1 .. 10 ; # valores no pasados ​​como la función Perl normal          

PHP

Antes de 4.0.1, PHP no admitía funciones anónimas. [66]

PHP 4.0.1 a 5.3

PHP 4.0.1 introdujo create_functioncuál era el soporte inicial para la función anónima. Esta llamada a función crea una nueva función con nombre aleatorio y devuelve su nombre (como una cadena)

$foo  =  create_function ( '$x' ,  'return $x*$x;' ); $barra  =  crear_función ( " \$ x" ,  "return \$ x* \$ x;" ); eco  $foo ( 10 );

La lista de argumentos y el cuerpo de la función deben estar entre comillas simples o los signos de dólar deben tener caracteres de escape. De lo contrario, PHP asume que " $x" significa la variable $xy la sustituirá en la cadena (a pesar de que posiblemente no exista) en lugar de dejar " $x" en la cadena. Para funciones con comillas o funciones con muchas variables, puede resultar bastante tedioso garantizar que el cuerpo de la función prevista sea lo que interpreta PHP.

Cada invocación de create_functioncrea una nueva función, que existe para el resto del programa, y ​​no puede ser recolectada como basura , usando memoria en el programa de manera irreversible. Si esto se utiliza para crear funciones anónimas muchas veces, por ejemplo, en un bucle, puede causar problemas como sobrecarga de memoria.

PHP 5.3

PHP 5.3 agregó una nueva clase llamada Closurey un método mágico __invoke()que hace que una instancia de clase sea invocable. [67]

$x  =  3 ; $func  =  función ( $z )  {  return  $z  *  2 ;  }; eco  $func ( $x );  // imprime 6

En este ejemplo, $funces una instancia de Closurey echo $func($x)es equivalente a echo $func->__invoke($x). PHP 5.3 imita funciones anónimas pero no admite funciones anónimas verdaderas porque las funciones PHP todavía no son objetos de primera clase.

PHP 5.3 admite cierres, pero las variables deben indicarse explícitamente como tales:

$x  =  3 ; $func  =  función ()  uso ( & $x )  {  $x  *=  2 ;  }; $función (); eco  $x ;  // imprime 6

La variable $xestá vinculada por referencia, por lo que la invocación de $funcla modifica y los cambios son visibles fuera de la función.

PHP 7.4

Las funciones de flecha se introdujeron en PHP 7.4

$x  =  3 ; $func  =  fn ( $z )  =>  $z  *  2 ; eco  $func ( $x );  // imprime 6

Dialectos de Prolog

Logtalk

Logtalk utiliza la siguiente sintaxis para predicados anónimos (expresiones lambda):

{ FreeVar1 , FreeVar2 , ... } / [ LambdaParameter1 , LambdaParameter2 , ... ] >> Objetivo

Un ejemplo simple sin variables libres y usando un predicado de mapeo de lista es:

| ?- meta :: mapa([ X , Y ] >> ( Y  es  2 * X ), [ 1 , 2 , 3 ], Ys ). Ys  = [ 2 , 4 , 6 ]

También se admite el curry. El ejemplo anterior se puede escribir como:

| ?- meta :: mapa([ X ] >> ([ Y ] >> ( Y  es  2 * X )), [ 1 , 2 , 3 ], Ys ). Ys  = [ 2 , 4 , 6 ]

Prólogo visual

Las funciones anónimas (en general, predicados anónimos ) se introdujeron en Visual Prolog en la versión 7.2. [68] Los predicados anónimos pueden capturar valores del contexto. Si se crea en un miembro de objeto, también puede acceder al estado del objeto (capturándolo This).

mkAdderdevuelve una función anónima, que ha capturado el argumento Xen el cierre. La función devuelta es una función que agrega Xa su argumento:

cláusulas  mkAdder ( X )  =  {  ( Y )  =  X + Y  }.

Pitón

Python admite funciones anónimas simples a través del formulario lambda. [39] El cuerpo ejecutable de la lambda debe ser una expresión y no puede ser una declaración, lo cual es una restricción que limita su utilidad. El valor devuelto por lambda es el valor de la expresión contenida. Los formularios Lambda se pueden utilizar en cualquier lugar donde se puedan utilizar funciones ordinarias. Sin embargo, estas restricciones la convierten en una versión muy limitada de una función normal. Aquí hay un ejemplo:

>>> foo  =  lambda  x :  x  *  x >>> foo ( 10 ) 100

En general, la convención de Python fomenta el uso de funciones con nombre definidas en el mismo ámbito en el que normalmente se usaría una función anónima en otros lenguajes. Esto es aceptable ya que las funciones definidas localmente implementan todo el poder de los cierres y son casi tan eficientes como el uso de una lambda en Python. En este ejemplo, se puede decir que la función de potencia incorporada ha sido curry :

>>> def  make_pow ( n ): ...  def  fix_exponent_pow ( x ): ...  return  pow ( x ,  n ) ...  return  fix_exponent_pow ... >>> sqr  =  make_pow ( 2 ) >>> sqr ( 10 ) 100 >>> cachorro  =  make_pow ( 3 ) >>> cachorro ( 10 ) 1000

R

En R las funciones anónimas se definen usando la sintaxis function(argument-list)expression, que tiene una abreviatura desde la versión 4.1.0 \, similar a Haskell.

> f <- función ( x ) x * x ; f ( 8 ) [1] 64 > ( función ( x , y ) x + y )( 5 , 6 ) [1] 11 > # Desde R 4.1.0 > ( \ ( x , y ) x + y )( 5 , 6 ) [1] 11     

rakú

En Raku , todos los bloques (incluso aquellos asociados con if, while, etc.) son funciones anónimas. Un bloque que no se utiliza como rvalue se ejecuta inmediatamente.

  1. Totalmente anónimo, llamado tal como fue creado.
    { decir  "Me llamaron" };
  2. asignado a una variable
    mi  $cuadrado1 = -> $x { $x * $x }; #2a. bloque puntiagudo mi  $squarer2 = { $^x * $^x }; #2b. twigil mi  $cuadrado3 = { mi  $x = shift  @_ ; $x * $x }; #2c. estilo Perl 5
  3. zurra
    sub  agregar ( $m , $n ) { $m + $n } mis  $siete = agregar ( 3 , 4 ); mi  $add_one = &añadir . suponiendo ( m => 1); mi $ocho =  $add_one ( $siete );
  4. Objeto AnyCode
    mi  $w = * - 1 ; # Objeto AnyCode mi  $b = { $_ - 1 }; # misma funcionalidad, pero como bloque invocable

Rubí

Ruby admite funciones anónimas mediante el uso de una estructura sintáctica llamada bloque . Hay dos tipos de datos para bloques en Ruby. ProcLos s se comportan de manera similar a los cierres , mientras que lambdalos s se comportan de manera más análoga a una función anónima. [42] Cuando se pasa a un método, un bloque se convierte en un Proc en algunas circunstancias.

# Ejemplo 1: # Funciones puramente anónimas que utilizan bloques. ex = [ 16 . 2 , 24 . 1 , 48 . 3 , 32 . 4 , 8 . 5 ] => [ 16 . 2 , 24 . 1 , 48 . 3 , 32 . 4 , 8 . 5 ] ej . ordenar_por { | x | x - x . to_i } # Ordenar por parte fraccionaria, ignorando la parte entera. => [ 24 . 1 , 16 . 2 , 48 . 3 , 32 . 4 , 8 . 5 ]                       # Ejemplo 2: # Funciones de primera clase como un objeto explícito de Proc - ex = Proc . new { pone "¡Hola mundo!" } => #<Proc:0x007ff4598705a0@(irb):7> ej . llamar ¡ Hola mundo! => nulo         # Ejemplo 3: # Función que devuelve un objeto de función lambda con parámetros def multiple_of? ( n ) lambda { | x | x % n == 0 } fin => nil multiple_four = multiple_of? ( 4 ) => #<Proc:0x007ff458b45f88@(irb):12 (lambda)> multiple_four . llamar ( 16 ) => verdadero múltiple_cuatro [ 15 ] => falso             

Óxido

En Rust , las funciones anónimas se denominan cierres. [69] Se definen utilizando la siguiente sintaxis:

|< parámetro - nombre > : < tipo >| -  > <retorno-tipo> { <cuerpo> } ;   

Por ejemplo:

sea ​​f = | x : i32 | -> i32 { x * 2 };         

Sin embargo, con la inferencia de tipos, el compilador puede inferir el tipo de cada parámetro y el tipo de retorno, por lo que el formulario anterior se puede escribir como:

sea ​​f = | x | { x * 2 };        

Con cierres con una sola expresión (es decir, un cuerpo con una línea) y tipo de retorno implícito, se pueden omitir las llaves:

sea ​​f = | x | x * 2 ;      

Los cierres sin parámetro de entrada se escriben así:

sea ​​f = || imprimir! ( "¡Hola Mundo!" );    

Los cierres se pueden pasar como parámetros de entrada de funciones que esperan un puntero de función:

// Una función que toma un puntero de función como argumento y lo llama con // el valor `5`. fn  apply ( f : fn ( i32 )  -> i32 )  -> i32  { // Sin punto y coma, para indicar un retorno implícito f ( 5 ) }  fn  main () { // Definiendo el cierre let f = | x | x * 2 ;          imprimir! ( "{}" , aplicar ( f )); // 10 imprimir! ( "{}" , f ( 5 )); // 10 }     

Sin embargo, es posible que se necesiten reglas complejas para describir cómo se capturan los valores en el cuerpo del cierre. Se implementan utilizando los rasgos Fn, FnMuty FnOnce: [70]

Con estas características, el compilador capturará variables de la manera menos restrictiva posible. [70] Ayudan a regular cómo se mueven los valores entre ámbitos, lo cual es muy importante ya que Rust sigue una construcción de por vida para garantizar que los valores se "tomen prestados" y se muevan de una manera predecible y explícita. [71]

A continuación se demuestra cómo se puede pasar un cierre como parámetro de entrada utilizando el Fnrasgo:

// Una función que toma un valor de tipo F (que se define como // un tipo genérico que implementa el rasgo `Fn`, por ejemplo, un cierre) // y lo llama con el valor `5`. fn  apply_by_ref < F > ( f : F )  -> i32  donde F : Fn ( i32 ) -> i32 { f ( 5 ) }   fn  principal () { sea f = | x | { imprimir! ( "Obtuve el valor: {}" , x ); x * 2 }; // Aplica la función antes de imprimir su valor de retorno println! ( "5 * 2 = {}" , apply_by_ref ( f )); }                // ~~ Salida del programa ~~ // Obtuve el valor: 5 // 5 * 2 = 10

La definición de función anterior también se puede acortar por conveniencia de la siguiente manera:

fn  apply_by_ref ( f : impl Fn ( i32 ) -> i32 ) -> i32 { f ( 5 ) }     

escala

En Scala , las funciones anónimas utilizan la siguiente sintaxis: [72]

( x : Int , y : Int ) => x + y       

En ciertos contextos, como cuando una función anónima es un parámetro que se pasa a otra función, el compilador puede inferir los tipos de parámetros de la función anónima y pueden omitirse en la sintaxis. En tales contextos, también es posible utilizar una abreviatura de funciones anónimas utilizando el carácter de subrayado para introducir parámetros sin nombre.

lista val = Lista ( 1 , 2 , 3 , 4 ) lista . reduceLeft ( ( x , y ) => x + y ) // Aquí, el compilador puede inferir que los tipos de xey son ambos Int. // Por lo tanto, no necesita anotaciones de tipo en los parámetros de la función anónima.              lista . reduceLeft ( _ + _ ) // Cada guión bajo representa un nuevo parámetro sin nombre en la función anónima. // Esto da como resultado un equivalente aún más corto a la función anónima anterior.     

Charla

En Smalltalk, las funciones anónimas se denominan bloques y se invocan enviándoles un mensaje de "valor". Si se van a pasar varios argumentos, se debe utilizar un mensaje "valor:...valor:" con el número correspondiente de argumentos de valor.

Por ejemplo, en GNU Smalltalk ,

st >  f := [ : x | x * x ] .  valor f :  8 . 64 st> [ : x : y | x + y ] valor: 5 valor: 6 . 11       

Los bloques de Smalltalk son técnicamente cierres, lo que les permite sobrevivir a su alcance definitorio y seguir haciendo referencia a las variables declaradas en ellos.

st >  f  := [ : a | [ : norte | a + n ]] valor:  100  . a  BlockClosure "devuelve el bloque interno, que agrega 100 (capturado en la variable " a ") a su argumento". st>  valor f :  1 . 101 st> valor f : 2 . 102      

Rápido

En Swift , las funciones anónimas se denominan cierres. [46] La sintaxis tiene la siguiente forma:

{ ( parámetros ) -> tipo de retorno en declaración }     

Por ejemplo:

{ ( s1 : Cadena , s2 : Cadena ) -> Bool a cambio s1 > s2 }           

En aras de la brevedad y la expresividad, los tipos de parámetros y el tipo de retorno se pueden omitir si se pueden inferir:

{ s1 , s2 a cambio s1 > s2 }        

De manera similar, Swift también admite declaraciones de devolución implícitas para cierres de una sola declaración:

{ s1 , s2 en s1 > s2 }       

Finalmente, los nombres de los parámetros también se pueden omitir; cuando se omiten, se hace referencia a los parámetros utilizando nombres abreviados de argumentos, que consisten en el símbolo $ seguido de su posición (por ejemplo, $0, $1, $2, etc.):

{ $0 > $1 }    

tcl

En Tcl , aplicar la función de elevación al cuadrado anónima a 2 tiene el siguiente aspecto: [73]

aplicar { x {expr { $x * $x }}} 2 # devuelve 4    

Este ejemplo involucra dos candidatos para lo que significa ser una función en Tcl. El más genérico suele denominarse prefijo de comando , y si la variable f contiene dicha función, entonces la forma de realizar la aplicación de la función f ( x ) sería

{ * } $f $x 

¿Dónde {*}está el prefijo de expansión (nuevo en Tcl 8.5)? El prefijo de comando en el ejemplo anterior es aplicar. {x {expr {$x*$x}}}Los nombres de los comandos se pueden vincular a prefijos de comando mediante el interp aliascomando. Los prefijos de comando admiten curry . Los prefijos de comando son muy comunes en las API de Tcl .

El otro candidato para "función" en Tcl generalmente se llama lambda y aparece como {x {expr {$x*$x}}}parte del ejemplo anterior. Esta es la parte que almacena en caché la forma compilada de la función anónima, pero solo puede invocarse pasándola al applycomando. Lambdas no admite el curry, a menos que se combine con an applypara formar un prefijo de comando. Las lambdas son raras en las API de Tcl.

vala

En Vala , las funciones anónimas se admiten como expresiones lambda. [74]

delegado int IntOp ( int x , int y );      void main () { IntOp foo = ( x , y ) => x * y ; salida estándar . printf ( "%d \n " , foo ( 10 , 5 )); }            

Visual Basic .NET

Visual Basic .NET 2008 introdujo funciones anónimas a través del formulario lambda. Combinado con la escritura implícita, VB proporciona una sintaxis económica para funciones anónimas. Al igual que con Python, en VB.NET las funciones anónimas deben definirse en una línea; no pueden ser declaraciones compuestas. Además, una función anónima en VB.NET debe ser realmente VB.NET Function: debe devolver un valor.

Dim foo = Función ( x ) x * x Consola . Línea de escritura ( foo ( 10 ))      

Visual Basic.NET 2010 agregó soporte para expresiones lambda multilínea y funciones anónimas sin valor de retorno. Por ejemplo, una función para usar en un Thread.

Atenuado como sistema nuevo .Enhebrado . Thread ( Sub () For n As Integer = 0 To 10 'Contar hasta 10 Console . WriteLine ( n ) 'Imprimir cada número Next End Sub ) t . Comenzar ()                    

Ver también

Referencias

  1. ^ "Funciones de orden superior". learnyouahaskell.com . Consultado el 3 de diciembre de 2014 .
  2. ^ Fernández, Maribel (2009), Modelos de computación: una introducción a la teoría de la computabilidad, Temas de pregrado en Ciencias de la Computación, Springer Science & Business Media, p. 33, ISBN 9781848824348, El cálculo Lambda... fue introducido por Alonzo Church en la década de 1930 como una notación precisa para una teoría de funciones anónimas.
  3. ^ "Expresiones de función de flecha: JavaScript". MDN . Consultado el 21 de agosto de 2019 .
  4. ^ "Bash lambda". GitHub . 2019-03-08.
  5. ^ Bill Wagner. "Expresiones lambda: referencia de C#". docs.microsoft.com . Consultado el 24 de noviembre de 2020 .
  6. ^ "Apoyo de cierre". Archivado desde el original el 6 de enero de 2014 . Consultado el 5 de enero de 2014 .
  7. ^ "¿Qué hay de nuevo en ColdFusion 10?". Archivado desde el original el 6 de enero de 2014 . Consultado el 5 de enero de 2014 .
  8. ^ "Clojure - Funciones de orden superior". clojure.org . Consultado el 14 de enero de 2022 .
  9. ^ "Referencia COBOL administrada". Documentación de Micro Focus . Microenfoque . Archivado desde el original el 25 de febrero de 2014 . Consultado el 25 de febrero de 2014 .
  10. ^ "Funciones - Lenguaje de programación D". dlang.org . Consultado el 14 de enero de 2022 .
  11. ^ ab "Un recorrido por el idioma Dart". dardo.dev . Consultado el 24 de noviembre de 2020 .
  12. ^ "Métodos anónimos en Delphi - RAD Studio". docwiki.embarcadero.com . Consultado el 24 de noviembre de 2020 .
  13. ^ "Funciones: programación Dylan". opendylan.org . Consultado el 14 de enero de 2022 .
  14. ^ "docs/sintaxis". elm-lang.org . Consultado el 14 de enero de 2022 .
  15. ^ ab "Sintaxis de Erlang/Elixir: un curso intensivo". elixir-lang.github.com . Consultado el 24 de noviembre de 2020 .
  16. ^ ab "Erlang - Diversión". erlang.org . Consultado el 24 de noviembre de 2020 .
  17. ^ ab cartermp. "Expresiones Lambda: la palabra clave divertida: F#". docs.microsoft.com . Consultado el 24 de noviembre de 2020 .
  18. ^ "LAMBDA: la función definitiva de hoja de cálculo de Excel". microsoft.com . 25 de enero de 2021 . Consultado el 30 de marzo de 2021 .
  19. ^ "Cotizaciones - Documentación de factores" . Consultado el 26 de diciembre de 2015 . Una cita es una función anónima (un valor que denota un fragmento de código) que puede usarse como valor y llamarse usando los combinadores fundamentales.
  20. ^ "Frink". frinklang.org . Consultado el 24 de noviembre de 2020 .
  21. ^ ab "Funciones anónimas en GoLang". Documentos de GoLang . 9 de enero de 2020 . Consultado el 24 de noviembre de 2020 .
  22. ^ "Documentación de Gosu" (PDF) . Consultado el 4 de marzo de 2013 .
  23. ^ "Documentación maravillosa". Archivado desde el original el 22 de mayo de 2012 . Consultado el 29 de mayo de 2012 .
  24. ^ "Función anónima - HaskellWiki". wiki.haskell.org . Consultado el 14 de enero de 2022 .
  25. ^ "Lambda". Haxe: el conjunto de herramientas multiplataforma . Consultado el 14 de enero de 2022 .
  26. ^ "Funciones - JavaScript | MDN". desarrollador.mozilla.org . Consultado el 14 de enero de 2022 .
  27. ^ "Funciones · El lenguaje Julia". docs.julialang.org . Consultado el 24 de noviembre de 2020 .
  28. ^ "Funciones de orden superior y Lambdas: lenguaje de programación Kotlin". Kotlin . Consultado el 24 de noviembre de 2020 .
  29. ^ "Programación en Lua: 6". www.lua.org . Consultado el 24 de noviembre de 2020 .
  30. ^ "Programación Maple: 1.6: Funciones y expresiones anónimas - Centro de aplicaciones". www.maplesoft.com . Consultado el 24 de noviembre de 2020 .
  31. ^ "Funciones anónimas: MATLAB y Simulink". www.mathworks.com . Consultado el 14 de enero de 2022 .
  32. ^ "Manual de Maxima 5.17.1: 39. Definición de función". maths.cnam.fr . Consultado el 24 de noviembre de 2020 .
  33. ^ ab "Manual de Nim". nim-lang.github.io .
  34. ^ "Ejemplos de código: OCaml". ocaml.org . Consultado el 24 de noviembre de 2020 .
  35. ^ "GNU Octave: funciones anónimas". octava.org . Consultado el 24 de noviembre de 2020 .
  36. ^ "Función literal". Manual de usuario de OpenSCAD . Wikilibros . Consultado el 22 de febrero de 2021 .
  37. ^ ab "perlsub - Subrutinas de Perl - Navegador Perldoc". perldoc.perl.org . Consultado el 24 de noviembre de 2020 .
  38. ^ "PHP: Funciones anónimas - Manual". www.php.net . Consultado el 24 de noviembre de 2020 .
  39. ^ ab "6. Expresiones: documentación de Python 3.9.0". docs.python.org . Consultado el 24 de noviembre de 2020 .
  40. ^ "4.4 Funciones: lambda". docs.racket-lang.org . Consultado el 24 de noviembre de 2020 .
  41. ^ "Funciones". docs.raku.org . Consultado el 14 de enero de 2022 .
  42. ^ ab Sosinski, Robert (21 de diciembre de 2008). "Comprensión de Ruby Blocks, Procs y Lambdas". Reactivo.IO. Archivado desde el original el 31 de mayo de 2014 . Consultado el 30 de mayo de 2014 .
  43. ^ "Cierres: funciones anónimas que pueden capturar su entorno: el lenguaje de programación Rust". doc.rust-lang.org . Consultado el 14 de enero de 2022 .
  44. ^ "Funciones anónimas". Documentación de Scala . Consultado el 14 de enero de 2022 .
  45. ^ "Recitación 3: funciones de orden superior". www.cs.cornell.edu . Consultado el 14 de enero de 2022 .
  46. ^ ab "Cierres: el lenguaje de programación Swift (Swift 5.5)". docs.swift.org .
  47. ^ "Documentación: tipos cotidianos". www.typescriptlang.org . Consultado el 14 de enero de 2022 .
  48. ^ ab "Proyectos/Vala/Tutorial - ¡GNOME Wiki!". wiki.gnome.org . Consultado el 24 de noviembre de 2020 .
  49. ^ KathleenDollard (15 de septiembre de 2021). "Expresiones Lambda - Visual Basic". docs.microsoft.com . Consultado el 14 de enero de 2022 .
  50. ^ "Referencia del idioma/Términos/Predicados anónimos - wiki.visual-prolog.com". wiki.visual-prolog.com . Consultado el 14 de enero de 2022 .
  51. ^ "Función puramente anónima: introducción elemental a Wolfram Language". www.wolfram.com . Consultado el 14 de enero de 2022 .
  52. ^ "Lambdas, cierres y todo lo demás · Número 1048 · ziglang/zig". GitHub . Consultado el 21 de agosto de 2023 .
  53. ^ "Statement Exprs (usando la colección de compiladores GNU (GCC))". gcc.gnu.org . Consultado el 12 de enero de 2022 .
  54. ^ "Especificación de idioma para bloques: documentación de Clang 13". clang.llvm.org . Consultado el 14 de enero de 2022 .
  55. ^ "Expresiones lambda (desde C++ 11) - cppreference.com". es.cppreference.com . Consultado el 14 de enero de 2022 .
  56. ^ Järvi, Jaakko; Powell, Gary (sin fecha). "Capítulo 16. Boost.Lambda". Impulsar la documentación . Aumentar . Consultado el 22 de diciembre de 2014 .
  57. ^ abcdefg Skeet, Jon (23 de marzo de 2019). C# en profundidad . Manning. ISBN 978-1617294532.
  58. ^ ab Albahari, José (2022). C# 10 en pocas palabras . O'Reilly. ISBN 978-1-098-12195-2.
  59. ^ "Especificación del lenguaje C# 5.0". Centro de descarga de Microsoft .
  60. ^ "Novedades de JDK 8".
  61. ^ ab Los tutoriales de Java: expresiones Lambda, docs.oracle.com
  62. ^ "Capítulo 15. Expresiones". docs.oracle.com .
  63. ^ "jdk/LambdaMethod.java". GitHub .
  64. ^ "Programación en Lua - Más sobre funciones". Archivado desde el original el 14 de mayo de 2008 . Consultado el 25 de abril de 2008 .
  65. ^ "2.7. Funciones anónimas · GitBook". www.cs.cornell.edu .
  66. ^ http://php.net/create_function la parte superior de la página indica esto con "(PHP 4 >= 4.0.1, PHP 5)"
  67. ^ "PHP: rfc: cierres". wiki.php.net .
  68. ^ "Predicados anónimos".en Referencia del lenguaje Visual Prolog
  69. ^ "Cierres: óxido con el ejemplo". doc.rust-lang.org .
  70. ^ ab "Como parámetros de entrada: Rust por ejemplo". doc.rust-lang.org .
  71. ^ "Vidas: óxido con el ejemplo". doc.rust-lang.org .
  72. ^ "Sintaxis de funciones anónimas: documentación de Scala". Archivado desde el original el 23 de julio de 2013 . Consultado el 31 de diciembre de 2010 .
  73. ^ aplicar página del manual, consultado el 6 de septiembre de 2012.
  74. ^ Manual de referencia de Vala, consultado el 9 de junio de 2021.

enlaces externos