stringtranslate.com

Función anónima

En programación informática , una función anónima ( literal de función , expresión 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 utiliza una vez, o un número limitado de veces, una función anónima puede ser sintácticamente más ligera que utilizar una función con nombre. Las funciones anónimas son omnipresentes en los lenguajes de programación funcional y otros lenguajes con funciones de primera clase , donde cumplen el mismo papel para el tipo de función que los literales para otros tipos de datos .

Las funciones anónimas se originan 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 de las computadoras electrónicas. [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" hacen referencia 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 ) , y donde M es una expresión que utiliza x . Compárese con la sintaxis de Python de .lambda x: M

El nombre "función flecha" hace referencia al símbolo matemático " maps to ", xM . Compárese con la sintaxis de JavaScript de . [3]x => M

Usos

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

El uso de funciones anónimas es una cuestión de estilo. Su uso nunca es la única forma de resolver un problema; cada función anónima podría definirse como una función nombrada y llamarse por su nombre. Las funciones anónimas suelen proporcionar una notación más breve que la definición de funciones nombradas. En lenguajes que no permiten la definición de funciones nombradas en ámbitos locales, las funciones anónimas pueden proporcionar encapsulación a través de un ámbito localizado, sin embargo, el código en el cuerpo de dicha función anónima puede no ser reutilizable o susceptible de pruebas por separado. Las funciones anónimas cortas/simples utilizadas en expresiones pueden ser más fáciles de leer y comprender que las funciones nombradas definidas por separado, aunque sin un nombre descriptivo pueden ser más difíciles de entender.

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 instanciar la función para valores particulares, lo que puede ser más eficiente en un lenguaje de programación dinámico , más legible y menos propenso a errores que llamar a una función con nombre.

Los siguientes ejemplos están escritos en Python 3.

Clasificación

Al intentar ordenar de una manera no estándar, puede ser más fácil incluir la lógica de ordenació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 ordenación genérica que implementa un algoritmo de ordenación que ordenará objetos arbitrarios. Esta función generalmente acepta 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 . sort ( key = lambda  x :  len ( x )) >>>  a [ 'coche' ,  'bicicleta' ,  'casa' ]

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

lambda  x :  longitud ( x )

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

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

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

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

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

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

>>>  a  =  [ 10 ,  'número' ,  11.2 ] >>>  a . sort ( key = lambda  x :  x . __class__ . __name__ ) >>>  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 que se evalúan 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 ):  devuelve  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 )>>>  print ( 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 

Sería poco práctico crear una función para cada función de comparación posible y puede resultar demasiado incómodo mantener el umbral para su uso posterior. Independientemente del motivo por el que se utilice 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 de modo 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 una división por cualquier número entero se transforma en una que realiza una división por un número entero determinado.

>>>  def  divide ( x ,  y ): ...  devuelve  x  /  y>>>  def  divisor ( d ): ...  return  lambda  x :  divide ( x ,  d )>>>  mitad  =  divisor ( 2 ) >>>  tercio  =  divisor ( 3 )>>>  imprimir ( mitad ( 32 ),  tercio ( 32 )) 16.0  10.6666666666666666>>>  imprimir ( mitad ( 40 ),  tercio ( 40 )) 20.0  13.333333333333334

Si bien el uso de funciones anónimas quizás no sea común en la currificación, aún se puede utilizar. En el ejemplo anterior, la función divisor genera funciones con un divisor especificado. Las funciones half y third currifican la función divide con un divisor fijo.

La función divisor 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 de manera genérica, a menudo una construcción de bucle o un esquema de recursión. 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 map realiza una llamada a una 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 presentada 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 como Verdadero 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 map, se considera más apropiada la siguiente forma:

>>>  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 (en el caso de las listas, normalmente de izquierda a derecha, se denomina "plegado a la izquierda" reduceen Python) y acumula 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  reduce >>>  a  =  [ 1 ,  2 ,  3 ,  4 ,  5 ] >>>  reduce ( lambda  x , y :  x * y ,  a ) 120

Esto funciona

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 único valor. En cambio, tanto el mapa como el filtro se pueden crear utilizando el pliegue. 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 en su totalidad, en parte como alguna variante, o no las admiten en absoluto.

Esta tabla muestra algunas tendencias generales. En primer lugar, los lenguajes que no admiten funciones anónimas ( C , Pascal , Object Pascal ) son todos lenguajes de tipado estático. Sin embargo, los lenguajes de tipado estático pueden admitir funciones anónimas. Por ejemplo, los lenguajes ML son de tipado estático 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++ (por 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 para funciones anónimas, de modo que las funciones se pueden definir y pasar tan fácilmente como otros tipos de datos.

Ejemplos

Numerosos lenguajes admiten funciones anónimas o algo similar.

APL

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

 f ​​{ × } Como una función derivada f 1 2 3 1 4 9 g ⊢×⊢ Como un tren tácito de 3 funciones ( bifurcación ) g 1 2 3 1 4 9 h × Como una función tácita derivada h 1 2 3 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 [55] y Clang .

CCG

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

( { tipo_de_retorno nombre_de_funciones_anónimas ( parámetros ) { cuerpo_de_función } nombre_de_funciones_anónimas ; } )          

El siguiente ejemplo funciona únicamente con GCC. Debido a la forma en que se expanden las macros, l_bodyno pueden contener comas fuera de los paréntesis; GCC trata la coma como un delimitador entre los argumentos de la macro. El argumento l_ret_typese puede eliminar si __typeof__está disponible; en el siguiente ejemplo, el uso de __typeof__on array devolvería testtype *, que se puede desreferenciar para obtener 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<sizeof(fe_arr)/sizeof(fe_arrType);i++) { fe_arr[i] = fe_fn_body(&fe_arr[i]); } \ }typedef struct { int a ; int b ; } tipo de prueba ;      void printout ( const testtype * array ) { int i ; for ( i = 0 ; i < 3 ; ++ i ) printf ( "%d %d \n " , array [ i ].a , array [ i ] .b ) ; printf ( " \n " ); }                     int main ( void ) { tipo de prueba matriz [] = { { 0 , 1 }, { 2 , 3 }, { 4 , 5 } };          printout ( matriz ); /* la función anónima se proporciona como función para foreach */ forEachInArray ( testtype , matriz , lambda ( testtype , ( void * item ), { int temp = ( * ( testtype * ) item ) .a ; ( * ( testtype * ) item ) .a = ( * ( testtype * ) item ) .b ; ( * ( testtype * ) item ) .b = temp ; return ( * ( testtype * ) item ); })); printout ( matriz ); return 0 ; }                                       

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

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

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

El tipo de los bloques de arriba 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:

#include <stdio.h> #include <despacho/despacho.h>  int main ( void ) { void ( ^ bucle_de_conteo )() = ^ { for ( int i = 0 ; i < 100 ; i ++ ) printf ( "%d \n " , i ); printf ( "ah ah ah \n " ); };                   /* Pasar como parámetro a otra función */ dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 ), count_loop );   /* Invocar directamente */ count_loop ();  devuelve 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 , [57] que tienen la forma:

[ captura ] ( parámetros ) especificaciones requiere ( 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 se tratara de 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 ) { devolver x + y ; }         

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

[] // Sin capturas, la lambda se puede convertir de forma implícita en un puntero a función. [ x , & y ] // x se captura por valor y y se captura por referencia. [ & ] // Cualquier variable externa se captura de forma implícita por referencia si se utiliza . [ = ] // Cualquier variable externa se captura de forma implícita por valor si se utiliza. [ & , x ] // x se captura por valor. Las demás variables se capturarán por referencia. [ = , & z ] // z se captura por referencia. Las demás variables se capturarán por valor.         

Las variables capturadas por valor son constantes de forma predeterminada. Si se agregan mutabledespués de la lista de parámetros, se vuelven no constantes.

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

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

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

std :: vector < int > some_list { 1 , 2 , 3 , 4 , 5 }; int total = 0 ; std :: for_each ( begin ( some_list ), end ( some_list ), [ & 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 }; int total = 0 ; int valor = 5 ; std :: for_each ( begin ( alguna_lista ), end ( alguna_lista ), [ & total , valor , esto ]( int x ) { total += x * valor * esto -> alguna_función (); });                            

Esto hará totalque se almacene como referencia, pero valuese almacenará como una copia.

La captura de thises especial. Solo se puede capturar por valor, no por referencia. Sin embargo, en C++17 , el objeto actual se puede capturar por valor (denotado por *this), o se puede capturar por referencia (denotado 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 de forma explícita o implícita, también se prueba el alcance de los miembros de la clase incluidos. Para acceder a los miembros de thisno es necesario el uso explícito de this->la 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 la inserción en línea y, por lo tanto, no necesitan almacenamiento adicional para referencias.

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

Las funciones lambda son objetos de función de un tipo que depende de la implementación; el nombre de este tipo solo 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 objeto std::functiono un objeto similar para capturar el valor lambda. El uso de la autopalabra clave puede ayudar a almacenar la función lambda.

auto mi_función_lambda = [ & ]( int x ) { /*...*/ }; auto mi_función_lambda_onheap = nuevo auto ([ = ]( int x ) { /*...*/ });               

A continuación se muestra un ejemplo de cómo almacenar funciones anónimas en variables, vectores y matrices y pasarlas como parámetros con nombre:

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

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 expresión lambda. Por lo tanto, esto es legal:

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

Desde C++17 , se puede declarar una lambda constexpry, 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 ser staticsi no tiene capturas. No se permite combinar los especificadores staticy .mutable

También desde C++23 una expresión lambda puede ser recursiva a través de explicit thiscomo primer parámetro:

auto fibonacci = []( este auto yo mismo , int n ) { devuelve n <= 1 ? n : yo mismo ( n - 1 ) + yo mismo ( 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 toma argumentos incluso si la lambda tiene un especificador. También hizo que una secuencia de especificadores de atributos que aparezca antes de la lista de parámetros, los especificadores de 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 del operador de llamada de función o a la plantilla de operador. Anteriormente, dicha secuencia siempre se aplicaba al tipo del operador de llamada de función o a la plantilla de operador del tipo de cierre, lo que hacía que, por ejemplo, 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: [58]

para_cada ( a.begin (), a.end ( ) , 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:

[ captura ] < tparams > requiere ( opcional ) ( parámetros ) especificaciones requiere ( opcional ) { cuerpo }              

DO#

En C# , el soporte para 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. [59] : 7–8  [60] : 26  C# las denomina expresiones lambda , siguiendo la versión original de funciones anónimas, el cálculo lambda . [61] [59] : 7–8, 91  [60] : 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 tipificada implícitamente, porque la sintaxis lambda se puede usar para denotar una función anónima o un árbol de expresiones, y el compilador no puede decidir automáticamente la elección. [59] : 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 un 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 values ​​= new List < int > () { 7 , 13 , 4 , 9 , 3 }; // Asigna la función anónima a todos los elementos de la lista y devuelve la nueva lista var foo = values ​​. ConvertAll ( d => d * d ) ; // El resultado de la variable foo es del 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 . [59] : 6  C# las denomina expresiones lambda , siguiendo la versión original de funciones anónimas, el cálculo lambda . [59] : 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 usa 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 bloques de declaraciones en línea sin nombre que se pueden ejecutar en una invocación de delegado. [59] : 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:

 public class TestDriver { delegate int SquareDelegate ( int d ); static int Square ( int d ) { return d * d ; } static void Main ( string [ ] args ) { // C# 1.0: Se necesita la sintaxis de delegado original // inicializando con un método nombrado. SquareDelegate A = new SquareDelegate ( Square ); System.Console.WriteLine ( 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 = delegate ( int d ) { return d * d ; }; System.Console.WriteLine ( 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. SquareDelegate C = x => x * x ; System . Console . WriteLine ( 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<>. System . Func < int , int > D = x => x * x ; System . Console . WriteLine ( 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 se expone al código de la aplicación excepto mediante el uso de la reflexión . [59] : 103  En el caso de la versión C# 3.0, se aplica el mismo mecanismo.

Lenguaje de marcado ColdFusion (CFML)

Usando elfunciónpalabra clave:

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

O usando una función de flecha:

fn  =  ()  =>  {  // declaraciones };fn  =  ()  =>  singleExpression  // singleExpression se devuelve de forma implícita. No es necesario utilizar llaves ni la palabra clave returnfn  =  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 utilizar 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 ){  devolver  n  >  1  ?  n  *  factorial ( n - 1 )  :  1 ; };

Las funciones anónimas CFML implementan el cierre.

D

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

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

Si no hay ambigüedades, se pueden omitir el tipo de retorno y la palabra clave delegate .

( x ){ return x * x ;} delegate ( x ){ return x * x ;} // si se necesita más verbosidad ( int x ){ return x * x ;} // si no se puede inferir el tipo de parámetro delegate ( int x ){ return x * x ;} // lo mismo delegate 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 no es necesario; la scopepalabra clave se puede utilizar para forzar la asignación en la pila. Desde la versión 2.058, es posible utilizar la 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 utilizarla de la siguiente manera:

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

Dardo

Dart admite funciones anónimas. [12]

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 ; tipo TSimpleProcedure = referencia al procedimiento ; TSimpleFunction = referencia a la función ( const x : string ) : entero ;             var x1 : TSimpleProcedure ; y1 : TSimpleFunction ;    begin x1 := procedimiento begin Writeln ( 'Hola Mundo' ) ; end ; x1 ; //invocar el método anónimo recién definido         y1 := function ( const x : string ) : Entero begin Resultado := Longitud ( x ) ; end ; Writeln ( y1 ( 'bar' )) ; end .            

PascalABC.NET

PascalABC.NET admite funciones anónimas que utilizan la sintaxis lambda

comienza var n := 10000000 ; var pp := ( 1 .. n ) . Selecciona ( x -> ( Aleatorio , Aleatorio )) . Donde ( p -> Sqr ( p [ 0 ]) + Sqr ( p [ 1 ]) < 1 ) . Conde / n * 4 ; Imprimir ( pp ) ; fin .                         

Elixir

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

suma = fn ( a , b ) -> a + b fin suma . ( 4 , 3 ) #=> 7         cuadrado = fn ( x ) -> x * x fin de enumeración . map [ 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. [17]

% Función anónima ligada a la variable Cuadrado Cuadrado = fun ( X ) -> X * X fin .       % Función nombrada con la misma funcionalidad cuadrado ( X ) -> X * X .    

Ir

Go admite funciones anónimas. [22]

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

Haskell

Haskell utiliza una sintaxis concisa para funciones anónimas (expresiones lambda). La barra invertida debe parecerse 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                    

Hacha

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

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

Java

Java admite funciones anónimas, llamadas expresiones Lambda , a partir del JDK 8. [ 62]

Una expresión lambda consta de una lista separada por comas de los parámetros formales encerrados 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 de un bloque de declaraciones. [63]

// sin parámetros () -> System . out . println ( "Hola, mundo." )  // con un parámetro (este ejemplo es una función identidad). a -> a  // con una expresión ( a , b ) -> a + b     // con información de tipo explícita ( id largo , 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 de lambda. Necesita un bloque de código. // Este ejemplo también incluye dos expresiones lambda anidadas (la primera también es un cierre). ( id , defaultPrice ) -> { Opcional < Producto > producto = productList . stream (). filter ( p -> p . getId () == id ). findFirst (); return producto . map ( p -> p . getPrice ()). orElse ( defaultPrice ); }               

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), [63] como en el siguiente ejemplo:

clase pública Calculadora { interfaz IntegerMath { int operación ( int a , int b );            predeterminado IntegerMath swap () { return ( a , b ) -> operación ( b , a ); } }            privado estático int aplicar ( int a , int b , IntegerMath op ) { devolver op . operación ( a , b ); }              public static void main ( String ... args ) { IntegerMath suma = ( a , b ) - > a + b ; IntegerMath resta = ( a , b ) -> a - b ; System.out.println ( "40 + 2 = " + aplicar ( 40 , 2 , suma ) ); System.out.println ( " 20 - 10 = " + aplicar ( 20 , 10 , resta ) ) ; System.out.println ( " 10 - 20 = " + aplicar ( 20 , 10 , resta.swap ( ) ) ) ; } }                                        

IntegerMathEn este ejemplo, se declara una interfaz funcional llamada . Las expresiones Lambda que la implementan IntegerMathse pasan al apply()método que se va a ejecutar. Los métodos predeterminados son como swaplos métodos definidos en las funciones.

Java 8 introdujo otro mecanismo llamado referencia de método (el ::operador) para crear una expresión lambda en un método existente. Una referencia de método no indica la cantidad ni los tipos de argumentos porque estos 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 ilustrarlo, en el siguiente ejemplo, anonymousClassy lambdaExpressionson instancias de IntegerMathque suman sus dos parámetros:

IntegerMath anonymousClass = new IntegerMath () { @Override public int operación ( int a , int b ) { devolver a + b ; } }; IntegerMath lambdaExpression = ( a , b ) -> a + b ;                          

La principal diferencia aquí es que la expresión lambda no necesariamente necesita asignar una nueva instancia para IntegerMath, y puede devolver la misma instancia cada vez que se ejecuta este código. [64] Además, al menos en la implementación de OpenJDK , las lambdas se compilan para invocar instrucciones dinámicas , con el cuerpo de lambda insertado como un método estático en la clase circundante, [65] 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 ){ return 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 ) por 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 URL en sí), 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 (externo) declara una función anónima, que luego se ejecuta cuando se utiliza con el último par de paréntesis. Esto es casi equivalente a lo siguiente, que llena el entorno con fa diferencia de una función anónima.

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 (){ return documento . título = ubicación . href ;}()); 

o simplemente:

void ( 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 una consecuencia directa de la evaluación de expresiones entre paréntesis. Las siguientes construcciones, llamadas expresiones de función invocadas inmediatamente, lo ilustran:

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

y

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

Representando " function(){ ... }" por f, la forma de los constructos 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 de parámetro formal 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 ser legal en JavaScript. (Aparte: por ejemplo, el ()'s podría ser ([],{},42,"abc",function(){}) siempre que la expresión evalúe una función).

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

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

Más correctamente, pero con salvedades,

( función (){ cosas }() ) ~= Un_punto_fijo_de ( función (){ devolver función (){ devolver ... { devolver función (){ cosas }() } ... }() }() )                 

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

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 que 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 e iterativa de un motor, especialmente la recursión 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 mediante 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 su primer elemento. La lista contiene la lista de argumentos, la documentación o las declaraciones y el cuerpo de una función. Las expresiones lambda se pueden utilizar dentro de formas lambda y con el operador especial "función".

( función ( lambda ( arg ) ( hacer-algoarg ) ))    

"Función" se puede abreviar como #'. También existe la macro lambda , que se expande en forma de función:

; usando comillas agudas #' ( 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 los 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 de x ) ( raíz cuadrada de y ))) 10.0 12.0 )         

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

( setf ( symbol-function 'sqr ) ( lambda ( x ) ( * x x ))) ; lo que nos permite llamarlo usando el nombre SQR: ( sqr 10.0 )        

Esquema

Las funciones nombradas de Scheme son simplemente azúcar sintáctica para funciones anónimas vinculadas a nombres:

( define ( somename arg ) ( haz-algo arg ))    

se expande (y es equivalente) a

( define somename ( lambda ( arg ) ( haz-algo arg )))     

Clojure

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

( función [ x ] ( + x3 ) )  

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 nombradas" de Clojure son simplemente azúcar sintáctica para las lambdas asociadas a nombres:

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

se expande a:

( def func ( función [ arg ] ( + 3 arg )))   

Lua

En Lua (como en Scheme) todas las funciones son anónimas. Una función nombrada en Lua es simplemente una variable que contiene una referencia a un objeto de función. [66]

Así, en Lua

función  foo ( x )  devuelve  2 * x  fin

es sólo azúcar sintáctico para

foo  =  función ( x )  devuelve  2 * x  fin

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

tabla.sort ( red ,  función ( a , b )  devuelve  a.nombre > b.nombrefin )  

Lenguaje Wolfram, Mathematica

El lenguaje Wolfram es el lenguaje de programación de Mathematica . Las funciones anónimas son importantes en la programación de esta última. Existen varias formas de crearlas. A continuación, se muestran algunas funciones anónimas que incrementan un número. La primera es la 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 & [ 5 , 6 ] 11    

Además, Mathematica tiene una construcción adicional para crear 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. Las variables que no se encuentran en la lista de argumentos se heredan del ámbito que las contiene y se capturan por valor.

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

Máxima

En Maxima las funciones anónimas se definen utilizando 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:

diversión  x  ->  x * 2

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

F#

F# admite funciones anónimas, [18] como sigue:

( diversión x -> x * x ) 20 // 400       

ML estándar

ML estándar admite funciones anónimas, como se detalla a continuación:

función arg => arg * arg

Nim

Nim admite funciones anónimas multilínea y multiexpresión. [34]

var anon = proc ( var1 , var2 : int ): int = var1 + var2 assert 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 ) 

Las funciones anónimas pueden pasarse como parámetros de entrada de otras funciones:

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

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

Perl

Perl 5

Perl 5 admite funciones anónimas, [38] como sigue:

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

Otras construcciones toman bloques simples 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.

my @squares = map { $_ * $_ } 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 = map { print for @_ } 1 .. 10 ; # valores no pasados ​​como una función Perl normal          

PHP

Antes de la versión 4.0.1, PHP no tenía soporte para funciones anónimas. [68]

PHP 4.0.1 a 5.3

PHP 4.0.1 introdujo la create_functionfunción anónima inicial. Esta llamada a función crea una nueva función con un nombre aleatorio y devuelve su nombre (como una cadena).

$foo  =  crear_funcion ( '$x' ,  'devolver $x*$x;' ); $bar  =  crear_funcion ( " \$ x" ,  "devolver \$ x* \$ x;" ); echo  $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 estar ocultos. 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 asegurarse de que el cuerpo de la función previsto sea lo que PHP interpreta.

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

PHP 5.3

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

$x  =  3 ; $func  =  function ( $z )  {  return  $z  *  2 ;  }; echo  $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  =  function ()  use ( & $x )  {  $x  *=  2 ;  }; $func (); echo  $x ;  // imprime 6

La variable $xestá vinculada por referencia, por lo que la invocación $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 ; echo  $func ( $x );  // imprime 6

Los dialectos de Prolog

Charla de registro

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

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

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

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

También se admite el currículo. El ejemplo anterior se puede escribir de la siguiente manera:

| ?- meta :: map([ 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. [70] Los predicados anónimos pueden capturar valores del contexto. Si se crean en un miembro de objeto, también pueden acceder al estado del objeto (mediante la captura de 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 de la forma lambda. [40] El cuerpo ejecutable de la lambda debe ser una expresión y no puede ser una declaración, lo que es una restricción que limita su utilidad. El valor devuelto por la lambda es el valor de la expresión contenida. Las formas lambda se pueden usar en cualquier lugar donde se puedan usar funciones ordinarias. Sin embargo, estas restricciones la convierten en una versión muy limitada de una función normal. A continuación se muestra 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 currificada :

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

R

En R las funciones anónimas se definen utilizando 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     

Raku

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

  1. Completamente anónimo, llamado como creado
    { decir  "me llamaron" };
  2. asignado a una variable
    mi  $cuadrado1 = -> $x { $x * $x }; # 2a. bloque puntiagudo mi  $cuadrado2 = { $^x * $^x }; # 2b. twigil mi  $cuadrado3 = { mi  $x = shift  @_ ; $x * $x }; # 2c. estilo Perl 5
  3. zurra
    sub  add ( $m , $n ) { $m + $n } mi  $siete = add ( 3 , 4 ); mi  $add_uno = &add . asumiendo ( m => 1); mi $ocho =  $add_uno ( $siete );
  4. Objeto WhateverCode
    mi  $w = * - 1 ; # objeto WhateverCode mi  $b = { $_ - 1 }; # misma funcionalidad, pero como bloque invocable

Rubí

Ruby admite funciones anónimas mediante una estructura sintáctica llamada block . 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. [43] Cuando se pasa a un método, un block 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 ] ex . sort_by { | 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 { puts "Hola, mundo!" } => #<Proc:0x007ff4598705a0@(irb):7> ex . call Hola , mundo! => nil         # Ejemplo 3: # Función que devuelve un objeto de función lambda con parámetros def multiple_of? ( n ) lambda { | x | x % n == 0 } end => nil multiple_four = multiple_of? ( 4 ) => #<Proc:0x007ff458b45f88@(irb):12 (lambda)> multiple_four . call ( 16 ) => true multiple_four [ 15 ] => false             

Óxido

En Rust , las funciones anónimas se denominan cierres. [71] 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 la forma 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 un tipo de retorno implícito, se pueden omitir las llaves:

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

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

sea ​​f = || println! ( "¡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 ;          println! ( "{}" , aplicar ( f )); // 10 println! ( "{}" , 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 , y : Fn[ FnMut72 ]FnOnce

Con estas características, el compilador capturará las variables de la manera menos restrictiva posible. [72] Ayudan a gobernar cómo se mueven los valores entre ámbitos, lo que 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. [73]

A continuación se muestra 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  main () { let f = | x | { println! ( "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 abreviar para mayor comodidad de la siguiente manera:

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

Escala

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

( 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 los parámetros de la función anónima y omitirlos en la sintaxis. En tales contextos, también es posible utilizar una abreviatura para funciones anónimas utilizando el carácter de subrayado para introducir parámetros sin nombre.

val list = List ( 1 , 2 , 3 , 4 ) list . reduceLeft ( ( x , y ) => x + y ) // Aquí, el compilador puede inferir que los tipos de x e y son ambos Int. // Por lo tanto, no necesita anotaciones de tipo en los parámetros de la función anónima.              list . 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 informal

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

Por ejemplo, en GNU Smalltalk ,

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

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

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

Rápido

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

{ ( parámetros ) -> returnType en la declaración }     

Por ejemplo:

{ ( s1 : Cadena , s2 : Cadena ) -> Bool en retorno s1 > s2 }           

Por motivos de brevedad y expresividad, los tipos de parámetros y el tipo de retorno se pueden omitir si se pueden inferir:

{ s1 , s2 en retorno s1 > s2 }        

De manera similar, Swift también admite declaraciones de retorno 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, los parámetros se referencian utilizando nombres de argumentos abreviados, que consisten en el símbolo $ seguido de su posición (por ejemplo, $0, $1, $2, etc.):

{ $0 > $1 }    

Tcl

En Tcl , la aplicación de la función de cuadratura anónima a 2 se ve de la siguiente manera: [75]

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 llamarse 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 

donde {*}es el prefijo de expansión (nuevo en Tcl 8.5). El prefijo de comando en el ejemplo anterior es apply {x {expr {$x*$x}}}Los nombres de comando se pueden vincular a prefijos de comando por medio del interp aliascomando. Los prefijos de comando admiten currying . Los prefijos de comando son muy comunes en las API de Tcl .

El otro candidato para "función" en Tcl se suele llamar 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 se puede invocar pasándola al applycomando. Las lambdas no admiten currificación, a menos que se emparejen con una applypara formar un prefijo de comando. Las lambdas son poco frecuentes en las API de Tcl.

Vala

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

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

Visual Basic .NET

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

Dim foo = Función ( x ) x * x Consola . WriteLine ( foo ( 10 ))      

Visual Basic.NET 2010 agregó compatibilidad con expresiones lambda de varias líneas y funciones anónimas sin un valor de retorno. Por ejemplo, una función para usar en un subproceso.

Dim t As New System . Threading . Thread ( Sub () Para n Como Entero = 0 A 10 'Contar hasta 10 Console . WriteLine ( n ) 'Imprimir cada número Siguiente Fin Sub ) t . Start ()                    

Véase 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 9781848824348El 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. ^ "Tipos de acceso". www.adaic.org . Consultado el 27 de junio de 2024 .
  5. ^ "Bash Lambda". GitHub . 8 de marzo de 2019.
  6. ^ BillWagner. "Expresiones Lambda - Referencia de C#". docs.microsoft.com . Consultado el 24 de noviembre de 2020 .
  7. ^ "Apoyo al cierre". Archivado desde el original el 6 de enero de 2014. Consultado el 5 de enero de 2014 .
  8. ^ "Novedades de ColdFusion 10". Archivado desde el original el 6 de enero de 2014. Consultado el 5 de enero de 2014 .
  9. ^ "Clojure - Funciones de orden superior". clojure.org . Consultado el 14 de enero de 2022 .
  10. ^ "Managed COBOL Reference". Documentación de Micro Focus . Micro Focus . Archivado desde el original el 25 de febrero de 2014 . Consultado el 25 de febrero de 2014 .
  11. ^ "Funciones - Lenguaje de programación D". dlang.org . Consultado el 14 de enero de 2022 .
  12. ^ ab "Un recorrido por el lenguaje Dart". dart.dev . Consultado el 24 de noviembre de 2020 .
  13. ^ "Métodos anónimos en Delphi - RAD Studio". docwiki.embarcadero.com . Consultado el 24 de noviembre de 2020 .
  14. ^ "Funciones: programación de Dylan". opendylan.org . Consultado el 14 de enero de 2022 .
  15. ^ "docs/syntax". elm-lang.org . Consultado el 14 de enero de 2022 .
  16. ^ ab "Sintaxis de Erlang/Elixir: un curso intensivo". elixir-lang.github.com . Consultado el 24 de noviembre de 2020 .
  17. ^ ab "Erlang -- Funs". erlang.org . Consultado el 24 de noviembre de 2020 .
  18. ^ ab cartermp. "Expresiones Lambda: La palabra clave divertida - F#". docs.microsoft.com . Consultado el 24 de noviembre de 2020 .
  19. ^ "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 .
  20. ^ "Citas - 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 se puede utilizar como valor y llamar mediante los combinadores fundamentales.
  21. ^ "Frink". frinklang.org . Consultado el 24 de noviembre de 2020 .
  22. ^ ab "Funciones anónimas en GoLang". GoLang Docs . 9 de enero de 2020 . Consultado el 24 de noviembre de 2020 .
  23. ^ "Documentación de Gosu" (PDF) . Consultado el 4 de marzo de 2013 .
  24. ^ "Documentación de Groovy". Archivado desde el original el 22 de mayo de 2012. Consultado el 29 de mayo de 2012 .
  25. ^ "Función anónima - HaskellWiki". wiki.haskell.org . Consultado el 14 de enero de 2022 .
  26. ^ "Lambda". Haxe: el kit de herramientas multiplataforma . Consultado el 14 de enero de 2022 .
  27. ^ "Funciones - JavaScript | MDN". developer.mozilla.org . Consultado el 14 de enero de 2022 .
  28. ^ "Funciones · El lenguaje Julia". docs.julialang.org . Consultado el 24 de noviembre de 2020 .
  29. ^ "Funciones de orden superior y lambdas: lenguaje de programación Kotlin". Kotlin . Consultado el 24 de noviembre de 2020 .
  30. ^ "Programación en Lua: 6". www.lua.org . Consultado el 24 de noviembre de 2020 .
  31. ^ "Programación en Maple: 1.6: Funciones y expresiones anónimas - Centro de aplicaciones". www.maplesoft.com . Consultado el 24 de noviembre de 2020 .
  32. ^ "Funciones anónimas - MATLAB y Simulink". www.mathworks.com . Consultado el 14 de enero de 2022 .
  33. ^ "Manual de Maxima 5.17.1: 39. Definición de función". maths.cnam.fr . Consultado el 24 de noviembre de 2020 .
  34. ^ ab "Manual de Nim". nim-lang.github.io .
  35. ^ "Ejemplos de código – OCaml". ocaml.org . Consultado el 24 de noviembre de 2020 .
  36. ^ "GNU Octave: Funciones anónimas". octave.org . Consultado el 24 de noviembre de 2020 .
  37. ^ "Function Literals". Manual de usuario de OpenSCAD . Wikilibros . Consultado el 22 de febrero de 2021 .
  38. ^ ab "perlsub - Subrutinas de Perl - Navegador Perldoc". perldoc.perl.org . Consultado el 24 de noviembre de 2020 .
  39. ^ "PHP: Funciones anónimas - Manual" www.php.net . Consultado el 24 de noviembre de 2020 .
  40. ^ ab "6. Expresiones — Documentación de Python 3.9.0". docs.python.org . Consultado el 24 de noviembre de 2020 .
  41. ^ "4.4 Funciones: lambda". docs.racket-lang.org . Consultado el 24 de noviembre de 2020 .
  42. ^ "Funciones". docs.raku.org . Consultado el 14 de enero de 2022 .
  43. ^ ab Sosinski, Robert (21 de diciembre de 2008). "Understanding Ruby Blocks, Procs and Lambdas". Reactive.IO. Archivado desde el original el 31 de mayo de 2014. Consultado el 30 de mayo de 2014 .
  44. ^ "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 .
  45. ^ "Funciones anónimas". Documentación de Scala . Consultado el 14 de enero de 2022 .
  46. ^ "Recitación 3: Funciones de orden superior". www.cs.cornell.edu . Consultado el 14 de enero de 2022 .
  47. ^ ab "Cierres: el lenguaje de programación Swift (Swift 5.5)". docs.swift.org .
  48. ^ "Documentación - Tipos cotidianos". www.typescriptlang.org . Consultado el 14 de enero de 2022 .
  49. ^ "Tipo de función - Documentación de Typst". typst.app . Consultado el 10 de septiembre de 2024 .
  50. ^ ab "Proyectos/Vala/Tutorial - Wiki de GNOME!". wiki.gnome.org . Consultado el 24 de noviembre de 2020 .
  51. ^ KathleenDollard (15 de septiembre de 2021). "Expresiones Lambda - Visual Basic". docs.microsoft.com . Consultado el 14 de enero de 2022 .
  52. ^ "Referencia del lenguaje/Términos/Predicados anónimos - wiki.visual-prolog.com". wiki.visual-prolog.com . Consultado el 14 de enero de 2022 .
  53. ^ "Función anónima pura: Introducción elemental al lenguaje Wolfram". www.wolfram.com . Consultado el 14 de enero de 2022 .
  54. ^ "Lambdas, cierres y todo lo demás · Número 1048 · ziglang/zig". GitHub . Consultado el 21 de agosto de 2023 .
  55. ^ "Expresiones de declaración (utilizando la colección de compiladores GNU (GCC))". gcc.gnu.org . Consultado el 12 de enero de 2022 .
  56. ^ "Especificación del lenguaje para bloques — Documentación de Clang 13". clang.llvm.org . Consultado el 14 de enero de 2022 .
  57. ^ "Expresiones Lambda (desde C++11) - cppreference.com". es.cppreference.com . Consultado el 14 de enero de 2022 .
  58. ^ Järvi, Jaakko; Powell, Gary (nd). "Capítulo 16. Boost.Lambda". Documentación de Boost . Boost . Consultado el 22 de diciembre de 2014 .
  59. ^ abcdefg Skeet, Jon (23 de marzo de 2019). C# en profundidad . Manning. ISBN 978-1617294532.
  60. ^ ab Albahari, José (2022). C# 10 en pocas palabras . O'Reilly. ISBN 978-1-098-12195-2.
  61. ^ "Especificación del lenguaje C# 5.0". Centro de descargas de Microsoft .
  62. ^ "Novedades en JDK 8".
  63. ^ ab Los tutoriales de Java: expresiones Lambda, docs.oracle.com
  64. ^ "Capítulo 15. Expresiones". docs.oracle.com .
  65. ^ "jdk/LambdaMethod.java". GitHub .
  66. ^ "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 .
  67. ^ "2.7. Funciones anónimas · GitBook". www.cs.cornell.edu .
  68. ^ http://php.net/create_function la parte superior de la página lo indica con "(PHP 4 >= 4.0.1, PHP 5)"
  69. ^ "PHP: rfc:cierres". wiki.php.net .
  70. ^ "Predicados anónimos".en Referencia del lenguaje Visual Prolog
  71. ^ "Cierres - Rust por ejemplo". doc.rust-lang.org .
  72. ^ ab "Como parámetros de entrada - Rust por ejemplo". doc.rust-lang.org .
  73. ^ "Vidas - Rust con el ejemplo". doc.rust-lang.org .
  74. ^ "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 .
  75. ^ aplicar página del manual, recuperada el 6 de septiembre de 2012.
  76. ^ Manual de referencia de Vala, consultado el 9 de junio de 2021.

Enlaces externos