Expresión lambdaEn el ámbito de la programación, una expresión lambda, también denominada función lambda, función literal o función anónima, es una subrutina definida que no está enlazada a un identificador. Las expresiones lambda a menudo son argumentos que se pasan a funciones de orden superior, o se usan 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 expresión lambda puede ser sintácticamente más simple que usar una función con nombre. Las funciones lambda son muy comunes en los lenguajes de programación funcional y en otros lenguajes con funciones de primera clase, en los que cumplen el mismo papel para el tipo de función que los literales para otros tipos de datos. Las funciones lambda se originaron debido al trabajo de Alonzo Church en su cálculo lambda ─en el que todas las funciones eran anónimas─ en 1936, antes de la invención de las computadoras electrónicas.[2] En varios lenguajes de programación, las funciones anónimas son introducidas bajo el nombre lambda y generalmente también son referidas como lambdas y abstracciones lambda. Las funciones anónimas han sido un aspecto integrado de los lenguajes de programación desde el origen del lenguaje Lisp en 1958, y un número creciente de lenguajes de programación admite funciones anónimas. Las funciones anónimas son una forma de funciones anidadas al permitir el acceso a variables ─no locales─ dentro de la función contenedora. Esto significa que las funciones anónimas necesitan ser implementadas utilizando clausuras o closures. A diferencia de las funciones nombradas anidadas, las funciones anónimas no pueden ser recursivas sin la asistencia de un operador de punto fijo o enlazarlas a un nombre.[3] Usos y FuncionesLas expresiones lambda pueden ser utilizadas para contener funcionalidades que no necesitan ser nombradas y normalmente se utilizan en un tiempo corto. Algunos ejemplos notables incluyen las clausuras y la currificación. El uso de expresiones lambda es un tema de estilo. Usar expresiones lambda como la única forma de resolver un problema es erróneo; cada expresión lambda puede en su lugar ser reemplazada por una función nombrada y llamada por su nombre. Algunos programadores utilizan las expresiones lambda para encapsular código específico y no reutilizable para así evitar código basura con muchas pequeñas funciones de pocas líneas. En algunos lenguajes de programación, las expresiones lambda normalmente son implementadas con propósitos específicos como la vinculación de eventos a devoluciones de llamada, o instanciar 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 de nombre más genérico. El código en las siguientes secciones está escrito en Python 2.x. ClasificaciónAl intentar ordenar de una manera no estándar, puede ser más fácil contener la lógica de comparación como una expresión lambda en lugar de crear una función con nombre. La mayoría de los lenguajes de programación proporcionan una función de clasificación genérica que implementa un algoritmo de ordenación que puede ordenar objetos arbitrarios. Esta función normalmente acepta una función de comparación arbitraria a la cual se le suministra dos elementos, la función indica si estos son iguales o si uno es mayor o menor que el otro (usualmente se indica mediante la devolución de un número negativo, cero o un número positivo). Considere clasificar una lista de cadenas por la longitud de la cadena: >>> a = ['casa', 'automóvil', 'avión']
>>> a.sort(lambda x,y: cmp(len(x), len(y)))
>>> print(a)
['casa', 'avión', 'automóvil']
La función anónima en este ejemplo es la expresión lambda: lambda x,y: cmp(...)
La función anónima acepta dos argumentos, >>> a = [10, 'number', 11.2]
>>> a.sort(lambda x,y: cmp(x.__class__.__name__, y.__class__.__name__))
>>> print(a)
[11.2, 10, 'number']
Nótese que ClausurasLas clausuras son funciones evaluadas en un entorno que contienen variables ligadas. El siguiente ejemplo vincula la variable "threshold" (umbral) en una función anónima que compara la entrada con el umbral. def comp(threshold):
return lambda x: x < threshold
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)
True True False False
>>> print func_b(5), func_b(8), func_b(13), func_b(21)
True True True False
Sería poco práctico crear una función para cada función de comparación posible y puede ser demasiado inconveniente para mantener el umbral alrededor para su uso posterior. Independientemente de la razón por la que se utiliza una clausura, la función anónima es la entidad que contiene la funcionalidad que hace la comparación. CurrificaciónCurrificación es el proceso de cambiar una función para que tome menos entradas (en este caso, transformar una función que realiza la división por cualquier número entero en uno que realiza la división por un entero ya establecido). >>> def divide(x, y):
... return x / y
>>> def divisor(d):
... return lambda x: divide(x, d)
>>> mitad = divisor(2)
>>> tercio = divisor(3)
>>> print mitad(32), tercio(32)
16 10
>>> print mitad(40), tercio(40)
20 13
Si bien el uso de funciones anónimas quizás no es común en la currificación, de todas formas se puede utilizar. En el ejemplo anterior, el divisor de funciones genera funciones con un divisor especificado. Las funciones mitad y tercio currifican la división utilizando un divisor fijo. La función del divisor también forma una clausura al vincular la variable "d". Funciones de orden superiorPython 2.x incluye varias funciones que toman funciones anónimas como argumento. Esta sección describe algunos de ellos. MapeoLa función de mapeo realiza una llamada de función en cada elemento de una lista. El siguiente ejemplo se aplica el cuadrado a cada elemento de una matriz con una función anónima. >>> a = [1, 2, 3, 4, 5, 6]
>>> print map(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 (calcula su cuadrado). La forma anterior es desaconsejada por los desarrolladores 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]
>>> print [x*x for x in a]
[1, 4, 9, 16, 25, 36]
FiltroLa función de filtro devuelve todos los elementos de una lista que al ser evaluados utilizando una determinada función regresan >>> a = [1, 2, 3, 4, 5, 6]
>>> print filter(lambda x: x % 2 == 0, a)
[2, 4, 6]
La función anónima comprueba si el argumento que se le pasa es par. La solución utilizando la estrategia de mapeo a continuación se considera más apropiado: >>> a = [1, 2, 3, 4, 5, 6]
>>> print [x for x in a if x % 2 == 0]
[2, 4, 6]
DoblarLa función de doblar / reducir se ejecuta sobre todos los elementos de una lista (normalmente de izquierda a derecha), acumulando un valor a medida que pasa. Un uso común de esto es combinar todos los elementos de una lista en un valor, por ejemplo: >>> a = [1, 2, 3, 4, 5]
>>> print reduce(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 una función doblar debe ser más de un solo valor. En su lugar, tanto el mapa como el filtro pueden crearse utilizando la función doblar. En el mapeo, 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 los elementos que coinciden con la condición dada. Lista de lenguajesA continuación se muestra una lista de los lenguajes de programación más populares que admiten funciones anónimas totalmente, parcialmente como alguna variante, o no lo admiten en lo absoluto. Esta tabla muestra algunas tendencias generales. En primer lugar, los idiomas que no admiten funciones anónimas (C, Pascal, Object Pascal) son todos lenguajes estatisticamente tipificados convencionales. Sin embargo, los lenguajes de tipo estático pueden admitir funciones anónimas. Por ejemplo, los lenguajes de marcas están escritos de forma estática y además incluyen funciones anónimas, y Delphi, un dialecto de Object Pascal, se ha extendido para soportar funciones anónimas. En segundo lugar, los idiomas que tratan las funciones como funciones de primera clase (Dylan, Haskell, JavaScript, Lisp, Lenguaje de marcado, Perl, Python, Ruby, Scheme) generalmente tienen soporte de funciones anónimas para que las funciones se puedan definir y pasar tan fácilmente como otros tipos de datos. Sin embargo, el nuevo estándar C++ 11 los añade a C++, a pesar de que este es un lenguaje convencional estáticamente tipado.
EjemplosNumerosos idiomas soportan funciones anónimas, o son capaces de realizar alguna función similar. C (extensión no estándar)La función anónima no es compatible con el lenguaje de programación C estándar, pero es soportada por algunas variables de C, como GCC y Clang. GCCEl GNU Compiler Collection (colección de compiladores GNU) (GCC) admite funciones anónimas, mezcladas con funciones anidadas y expresiones de sentencia. Tiene la forma: ( { Tipo_de_retorno Nombre_de_la_función_anónima(parámetros) { cuerpo_de_la_función} Nombre_de_la_función_anónima; } )
El siguiente ejemplo funciona solo con GCC. Debido a cómo se expanden las macros, #include <stdio.h>
//* Esta es la definición de una 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 __test
{
int a;
int b;
} testtype;
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)
{
testtype array[] = { {0,1}, {2,3}, {4,5} };
printout(array);
/* La función anónima se da como función para el foreach */
forEachInArray(testtype, array,
lambda (testtype, (void *item),
{
int temp = (*( testtype *) item).a;
(*( testtype *) item).a = (*( testtype *) item).b;
(*( testtype *) item).b = temp;
return (*( testtype *) item);
}));
printout(array);
return 0;
}
Clang (C, C++, Objective-C, Objective-C++)Clang soporta funciones anónimas, son llamadas bloques, los cuales tienen la forma: ^return_type ( parameters ) { function_body }
El tipo de los bloques anteriores es #include <stdio.h>
#include <dispatch/dispatch.h>
int main(void) {
void (^count_loop)() = ^{
for (int i = 0; i < 100; i++)
printf("%d\n", i);
printf("ah ah ah\n");
};
/* Se pasa como parámetro a otra función */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), count_loop);
/* Se invoca directamente */
count_loop();
return 0;
}
El código con bloques debe ser compilado con el parámetro C++ (desde C++11)C++11 soporta funciones anónimas, llamadas expresiones lambda , que tienen la forma: [capture](parameters) -> return_type { function_body }
Un ejemplo de función lambda se define de la siguiente forma: [](int x, int y) -> int { return x + y; }
C++11 también soporta clausuras.Las clausuras se definen entre corchetes ( [] //Sin variables definidas. Intentar utilizar cualquier variable externa en el lambda es un error.
[x, &y] //x se captura por valor, y se captura por referencia
[&] //Cualquier variable externa es capturada implícitamente por referencia si se utiliza
[=] //Cualquier variable externa es capturada implícitamente por valor si se utiliza
[&, x] //x se captura explícitamente por valor. Otras variables serán capturadas por referencia
[=, &z] //z se captura explícitamente por referencia. Otras variables serán capturadas por el valor
Las variables capturadas por valor son constantes por defecto. Agregar 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;
});
Esto calcula el total de todos los elementos de la lista. La variable std::vector<int> some_list{ 1, 2, 3, 4, 5 };
int total = 0;
int value = 5;
std::for_each(begin(some_list), end(some_list), [&, value, this](int x) {
total += x * value * this->some_func();
});
Esto hará que La implementación interna específica puede variar, pero la expectativa es que una función lambda que capture todo por referencia almacenará el puntero de pila real de la función en la que se crea, en lugar de referencias individuales a las variables de pila. Sin embargo, debido a que la mayoría de las funciones lambda son pequeñas y locales en el ámbito, son candidatos probables para expansión inline, y por lo tanto no necesitan almacenamiento añadido para las referencias. Si se invoca un objeto de clausura que contiene referencias a variables locales después del alcance del bloque más interno de su creación, el comportamiento es indefinido. Las funciones Lambda son objetos de función de un tipo dependiente 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 un parámetro, el tipo debe ser una plantilla, o debe crear un auto my_lambda_func = [&](int x) { /*...*/ };
auto my_onheap_lambda_func = new auto([=](int x) { /*...*/ });
A continuación se muestra un ejemplo de almacenamiento de funciones anónimas en variables, vectores y matrices; Y pasarlos como parámetros nombrados: #include <functional>
#include <vector>
#include <iostream>
double eval(std::function <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(int i=0;i<fv.size();i++)
std::cout << fv[i](2.0) << std::endl;
for(int i=0;i<3;i++)
std::cout << fa[i](2.0) << std::endl;
for(auto &f : fv)
std::cout << f(2.0) << std::endl;
for(auto &f : fa)
std::cout << f(2.0) << std::endl;
std::cout << eval(f0) << std::endl;
std::cout << eval(f1) << std::endl;
std::cout << eval([](double x){return x*x;}) << std::endl;
return 0;
}
Una expresión lambda con una especificación de captura vacía ( auto a_lambda_func = [](int x) { /*...*/ };
void (* func_ptr)(int) = a_lambda_func;
func_ptr(4); //llama a la expresión lambda.
Las bibliotecas Boost también proporcionan su propia sintaxis para las funciones lambda, utilizando la siguiente sintaxis:[11] for_each(a.begin(), a.end(), std::cout << _1 << ' ');
DD utiliza delegados en línea para implementar funciones anónimas. La sintaxis completa para un delegado en línea es: return_type delegate(arguments){/*body*/}
Si no es ambiguo, se puede 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;} // ditto
delegate double(int x){return x*x;} // Si el tipo de retorno debe ser forzado manualmente
Desde la versión 2.0, D asigna clausuras en la pila a menos que el compilador pueda probar que es innecesario; La palabra clave x => x*x;
(int x) => x*x;
(x,y) => x*y;
(int x, int y) => x*y;
Una función anónima puede asignarse a una variable y utilizarse de la siguiente manera: auto sqr = (double x){return x*x;};
double y = sqr(4);
DartDart permite funciones anónimas en la siguiente forma: var sqr = (x) => x * x;
print(sqr(5));
o print(((x) => x * x)(5));
DelphiDelphi introdujo funciones anónimas desde la versión 2009. program demo;
type
TSimpleProcedure = reference to procedure;
TSimpleFunction = reference to function(x: string): Integer;
var
x1: TSimpleProcedure;
y1: TSimpleFunction;
begin
x1 := procedure
begin
Writeln('Hello World');
end;
x1; //Invocar el método anónimo recién definido
y1 := function(x: string): Integer
begin
Result := Length(x);
end;
Writeln(y1('bar'));
end.
ElixirElixir usa las clausuras ( sum = fn(a, b) -> a + b end
sum.(4, 3)
#=> 7
square = fn(x) -> x * x end
Enum.map [1, 2, 3, 4], square
#=> [1, 4, 9, 16]
ErlangErlang utiliza una sintaxis para funciones anónimas similar a la de las funciones nombradas. % Función anónima vinculada a la variable "Square"
Square = fun(X) -> X * X end.
% Función nombrada con la misma funcionalidad
square(X) -> X * X.
GoGo soporta funciones anónimas. foo := func(x int) int {
return x * x
}
fmt.Println(foo(10))
HaskellHaskell usa una sintaxis concisa para funciones anónimas (expresiones lambda). \x -> x * x
Las expresiones Lambda están totalmente integradas con el motor de inferencia de tipo, y soportan toda la sintaxis y características de las funciones "ordinarias" (excepto el uso de múltiples definiciones para la correspondencia de patrones, ya que la lista de argumentos solo se especifica una vez). map (\x -> x * x) [1..5] -- returns [1, 4, 9, 16, 25]
Las siguientes expresiones son todas equivalentes: f x y = x + y
f x = \y -> x + y
f = \x y -> x + y
HaxeEn Haxe, las funciones anónimas son llamadas expresiones lambda, y utilizan la sintaxis var f = function(x) return x*x;
f(8); // 64
(function(x,y) return x+y)(5,6); // 11
JavaJava desde el JDK 8 soporta funciones anónimas, denominadas Expresiones Lambda.[12] Una expresión lambda consiste en 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 consistir en una sentencia o un bloque de sentencia.[13] // sin parámetros
() -> System.out.println("Hello, world.")
// Con un parámetro (este ejemplo es una función de identidad).
a -> a
// Con una expresión
(a, b) -> a + b
// Con información de tipo explícita
(long id, String name) -> "id: " + id + ", name:" + name
// Con un bloque de código
(a, b) -> { return a + b; }
// Con múltiples afirmaciones en el cuerpo lambda. Necesita un bloque de código.
// Este ejemplo también incluye dos expresiones lambda anidadas (la primera también es una clausura).
(id, defaultPrice) -> {
Optional<Product> product = productList.stream().filter(p -> p.getId() == id).findFirst();
return product.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[13]), como en el ejemplo siguiente: public class Calculator {
interface IntegerMath {
int operation(int a, int b);
default IntegerMath swap() {
return (a, b) -> operation(b, a);
}
}
private static int apply(int a, int b, IntegerMath op) {
return op.operation(a, b);
}
public static void main(String... args) {
IntegerMath addition = (a, b) -> a + b;
IntegerMath subtraction = (a, b) -> a - b;
System.out.println("40 + 2 = " + apply(40, 2, addition));
System.out.println("20 - 10 = " + apply(20, 10, subtraction));
System.out.println("10 - 20 = " + apply(20, 10, subtraction.swap()));
}
}
En este ejemplo, se declara una interfaz funcional denominada IntBinaryOperator sum = Integer::sum;
En el ejemplo anterior, la interfaz funcional Limitaciones en JavaLas expresiones lambda en Java 8 poseen las siguientes limitaciones:
JavaScriptJavaScript/ECMAScript permite el uso de funciones anónimas. alert((function(x){
return x*x;
})(10));
En ES6: alert((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. javascript:document.title=location.href;
Sin embargo, como la sentencia de asignación devuelve un valor (la propia URL), muchos navegadores crean una nueva página para mostrar este valor. En su lugar, una función anónima, que no devuelve un valor, se puede utilizar: javascript:(function(){document.title=location.href;})();
La sentencia de la función en el primer par de paréntesis (el paréntesis más externo) declara una función anónima, que se ejecuta cuando se utiliza con el último par de paréntesis. Esto es casi equivalente a lo siguiente, que puebla el entorno con javascript:var f = function(){document.title=location.href;}; f();
Se utilizan "Bookmarklets" para evitar nuevas páginas para funciones anónimas arbitrarias:
La sentencia de función en el primer par de paréntesis (el más externo) declara una función anónima, que se ejecuta cuando se utiliza con el último par de paréntesis. Esto es casi equivalente a lo siguiente, que completa el entorno con javascript:var f = function(){document.title=location.href;}; f();
Uso de "Bookmarklets" para evitar crear nuevas páginas para funciones anónimas arbitrarias: javascript:void(function(){return document.title=location.href;}());
O simplemente: javascript:void(document.title=location.href);
JavaScript posee ciertas 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 las expresiones entre paréntesis. Las siguientes construcciones que se llaman expresiones de funciones inmediatamente invocadas ilustran esto: (function(){ ... }())
y (function(){ ... })()
representando " (function(){( function(){( ... {( function(){cosas}() )} ... )}() )}() )
También, se puede escribir más correctamente, pero con precaución de la siguiente forma: ( function(){stuff}() ) ~=
A_Fixed_Point_of(
function(){ return function(){ return ... { return function(){stuff}() } ... }() }()
)
Hay que observar las implicaciones de la función anónima en los fragmentos de JavaScript que siguen:
JuliaEn el lenguaje de programación Julia se definen las funciones anónimas utilizando la sintaxis julia> f = x -> x*x; f(8)
64
julia> ((x,y)->x+y)(5,6)
11
LispLisp y Scheme soportan funciones anónimas utilizando la construcción "lambda", que es una referencia al cálculo lambda. Clojure soporta funciones anónimas con la forma especial (lambda (arg) (* arg arg))
Common LispCommon 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 entonces la lista de argumentos, la documentación o las declaraciones y un cuerpo de función. Las expresiones lambda se pueden utilizar dentro de las formas lambda y con el operador especial (function (lambda (arg) (do-something arg)))
; usando "#"
#'(lambda (arg) (haz-algo argumento))
; usando la macro "lambda":
(lambda (arg) (haz-algo argumento))
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 que una expresión lambda se escriba en una llamada de función: ((lambda (x y)
(+ (sqrt x) (sqrt y)))
10.0
12.0)
También es posible dar nombres globales más adelante a las funciones anónimas en Common Lisp: (setf (symbol-function 'sqr)
(lambda (x) (* x x)))
; which allows us to call it using the name SQR:
(sqr 10.0)
SchemeCuriosamente, en Scheme (lenguaje de programación), las funciones nombradas son simplemente "azúcar sintáctico" para funciones anónimas vinculadas a nombres: (define (Algún-nombre argumento)
(haz-algo argumento))
Se expande (y es equivalente) a: (define Algún-nombre
(lambda (argumento)
(haz-algo argumento)))
ClojureClojure soporta funciones anónimas a través de la forma especial "fn": (fn [x] (+ x 3))
También hay una sintaxis de lector para definir un 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áctico" para las lambdas vinculadas a los nombres: (defn func [arg] (+ 3 arg))
Se expande a: (def func (fn [arg] (+ 3 arg)))
LuaEn Lua (al igual que 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.[14] Así, en Lua: function foo(x) return 2*x end
Es simple azúcar sintáctico para: foo = function(x) return 2*x end
Un ejemplo de uso de funciones anónimas para ordenar en orden inverso: table.sort(network, function(a,b)
return a.name > b.name
end)
Las funciones anónimas son importantes en Mathematica. Hay varias maneras de crearlas. A continuación se muestran algunas funciones anónimas que incrementan un número. La primera es la más común. #1+1&
Function[x,x+1]
x \[Function] x+1
Así, por ejemplo: f:= #1^2&;f[8]
64
#1+#2&[5,6]
11
Además, Mathematica posee una construcción añadida para realizar funciones anónimas recursivas. El símbolo If[#1 == 1, 1, #1 * #0[#1-1]]&
MATLAB, OctaveLas funciones anónimas en MATLAB o Octave se definen mediante la sintaxis > f = @(x)x*x; f(8)
ans = 64
> (@(x,y)x+y)(5,6) % Solamente funciona en Octave
ans = 11
MaximaEn Maxima se definen funciones anónimas utilizando la sintaxis f: lambda([x],x*x); f(8);
64
lambda([x,y],x+y)(5,6);
11
MLLos diversos dialectos de ML (lenguaje de programación) admiten funciones anónimas. OCamlOCaml admite funciones anónimas de la siguiente forma: fun arg -> arg * arg
F#F# admite funciones anónimas, de la siguiente manera: (fun x -> x * x) 20 // 400
Standard MLStandard ML admite funciones anónimas, de la siguiente manera: fn arg => arg * arg PerlPerl 5Perl 5 admite funciones anónimas, en la siguiente forma: (sub { print "Fui llamado\n" })->(); # 1. Completamente anónimo, llamado en cuanto fue creado
my $squarer = sub { my $x = shift; $x * $x }; # 2. Asignado a una variable
sub curry {
my ($sub, @args) = @_;
return sub { $sub->(@args, @_) }; # 3. Como un valor de retorno de otra función
}
# Ejemplo de currificación en Perl
sub sum { my $tot = 0; $tot += $_ for @_; $tot } # retorna la suma de sus argumentos
my $curried = curry \&sum, 5, 7, 9;
print $curried->(1,2,3), "\n"; # muestra 27 ( = 5 + 7 + 9 + 1 + 2 + 3 )
Otras construcciones toman "bloques desnudos" como argumentos, que sirven 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á establecido. my @cuandrados = map { $_ * $_ } 1..10; # Map y grep no utilizan la palabra clave 'sub'
my @cuadrado2 = map $_ * $_, 1..10; # Paréntesis innecesarios para una expresión
my @ejemplo_incorrecto = map { print for @_ } 1..10; # Valores no son pasados como una función normal de Perl
Perl 6En Perl 6, todos los bloques (incluso aquellos asociados con if, while, etc.) son funciones anónimas. Se ejecuta inmediatamente un bloque que no se utiliza como valor rvalue. # Completamente anónimo, es llamado en cuanto se crea
{ say "Fui llamado" };
# Asignado a una variable
my $squarer1 = -> $x { $x * $x }; # 2a. Pointy block (expresión lambda)
my $squarer2 = { $^x * $^x }; # 2b. twigil
my $squarer3 = { my $x = shift @_; $x * $x }; # 2b. Estilo de Perl 5
# Currificación
sub suma ($m, $n) { $m + $n }
my $siete = suma(3, 4);
my $suma_uno = &suma.assuming(m => 1);
my $ocho = $suma_uno($siete);
PHPAntes de la versión 4.0.1, PHP no tenía soporte para funciones anónimas.[15] PHP 4.0.1 a 5.3PHP 4.0.1 introdujo la llamada $foo = create_function('$x', 'return $x*$x;');
$bar = create_function("\$x", "return \$x*\$x;");
echo $foo(10);
La lista de argumentos y el cuerpo de funciones deben estar en comillas simples, o en su defecto, los signos de dólar deben escaparse. De lo contrario, PHP asume que " En el ejemplo anterior, cada invocación de PHP 5.3PHP 5.3 agregó una nueva clase llamada $x = 3;
$func = function($z) { return $z *= 2; };
echo $func($x); // Muestra "6" en la salida
En el ejemplo anterior, PHP 5.3 soporta clausuras pero las variables deben ser explícitamente indicadas como tales: $x = 3;
$func = function() use(&$x) { $x *= 2; };
$func();
echo $x; // Muestra "6" en la salida
La variable Dialectos de PrologLogtalkLogtalk utiliza la siguiente sintaxis para expresiones anónimas (expresiones lambda): {FreeVar1, FreeVar2, ...}/[ParametroLambda1, ParametroLambda2, ...]>>Goal
Un ejemplo simple sin variables libres y usando un predicado de asignación de listas sería: | ?- meta::map([X,Y]>>(Y is 2*X), [1,2,3], Ys).
Ys = [2,4,6]
yes
La currificación también es soportada. Es posible escribir el ejemplo anterior como: | ?- meta::map([X]>>([Y]>>(Y is 2*X)), [1,2,3], Ys).
Ys = [2,4,6]
yes
Visual PrologLas funciones anónimas (en general los "predicados" anónimos) se introdujeron en la versión 7.2. de Visual Prolog.[17]
Los predicados anónimos pueden capturar valores desde el contexto. Si se crea el predicado en un miembro de objeto, este también puede acceder al estado del objeto (captando clauses
mkAdder(X) = { (Y) = X+Y }.
PythonPython soporta funciones anónimas simples a través de la forma lambda. El cuerpo ejecutable del lambda debe ser una expresión y no puede ser una declaración, la cual es una restricción que limita su utilidad. El valor devuelto por el lambda es el valor de la expresión que está contenida en esta. Las formas Lambda se pueden utilizar en cualquier lugar donde puedan funcionar las funciones ordinarias. Sin embargo, estas restricciones hacen que sea una versión muy limitada de una función normal. Por ejemplo: >>> foo = lambda x: x*x
>>> print(foo(10))
100
En general, las convenciones de Python fomentan el uso de funciones nombradas definidas en el mismo ámbito que uno podría utilizar normalmente funciones anónimas en otros idiomas. Esto es aceptable ya que las funciones definidas localmente implementan todo el poder de las clausuras y son casi tan eficientes como el uso de un lambda en Python. En el siguiente ejemplo, se puede decir que la función "potencia" ( >>> def make_pow(n):
... def fixed_exponent_pow(x):
... return pow(x, n)
... return fixed_exponent_pow
...
>>> sqr = make_pow(2)
>>> print (sqr(10))
100
>>> cub = make_pow(3)
>>> print (cub(10))
1000
REn GNU R las funciones anónimas son definidas utilizando la sintaxis > f <- function(x)x*x; f(8)
[1] 64
> (function(x,y)x+y)(5,6)
[1] 11
RubyRuby soporta funciones anónimas utilizando una estructura sintáctica llamada bloque. Hay dos tipos de datos para bloques en Ruby:
Cuando se pasa a un método, en algunas circunstancias un bloque se convierte en un " irb(main):001:0> # Ejemplo 1:
irb(main):002:0* # Funciones puramente anónimas utilizando bloques.
irb(main):003:0* ex = [16.2, 24.1, 48.3, 32.4, 8.5]
=> [16.2, 24.1, 48.3, 32.4, 8.5]
irb(main):004:0> 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]
irb(main):005:0> # Ejemplo 2:
irb(main):006:0* # Funciones de primera clase como un objeto explícito de Proc-
irb(main):007:0* ex = Proc.new { puts "Hola mundo!" }
=> #<Proc:0x007ff4598705a0@(irb):7>
irb(main):008:0> ex.call
Hola mundo!
=> nil
irb(main):009:0> # Ejemplo 3:
irb(main):010:0* # Función que retorna una función lambda como objeto con parámetros
irb(main):011:0* def is_multiple_of(n)
irb(main):012:1> lambda{|x| x % n == 0}
irb(main):013:1> end
=> nil
irb(main):014:0> multiple_four = is_multiple_of(4)
=> #<Proc:0x007ff458b45f88@(irb):12 (lambda)>
irb(main):015:0> multiple_four.call(16)
=> true
irb(main):016:0> multiple_four[15]
=> false
ScalaEn Scala, las funciones anónimas utilizan la siguiente sintaxis:[19] (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 se pueden omitir en la sintaxis. En tales contextos, también es posible utilizar una abreviatura para funciones anónimas que utilizan 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 Int.
// Por lo tanto, no necesita anotaciones de tipo sobre los parámetros de la función anónima.
list.reduceLeft( _ + _ )
// Cada subrayado representa un nuevo parámetro sin nombre en la función anónima.
// Esto resulta en un equivalente aún más corto a la función anónima anterior.
SmalltalkEn Smalltalk las funciones anónimas son llamadas bloques y poseen la siguiente estructura: [ :x | x*x ] value: 4
"returns 16"
SwiftEn Swift, las funciones anónimas son llamadas clausuras,[20] y poseen la siguiente estructura: { (parameters) -> returnType in
statement
}
Por ejemplo: { (s1: String, s2: String) -> Bool in
return s1 > s2
}
En aras de la brevedad y la expresividad, se pueden omitir los tipos de parámetro y el tipo de retorno si pueden inferirse: { s1, s2 in return s1 > s2 }
Del mismo modo, Swift también soporta declaraciones de devolución implícitas para cierres de una sola declaración: { s1, s2 in 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 }
fn = function(){
// statements
};
CFML admite cualquier declaración dentro de la definición de la función, no solamente expresiones, además CFML también admite funciones anónimas recursivas: factorial = function(n){
return n > 1 ? n * factorial(n-1) : 1;
};
Las funciones anónimas de CFML implementan clausuras. .NET FrameworkC#En C#, el soporte para funciones anónimas se ha profundizado a través de varias versiones del compilador de idiomas. La versión 3.0 del lenguaje, lanzada en noviembre de 2007 junto a .NET Framework v3.5, soporta completamente las funciones anónimas. En C# son llamadas "expresiones lambda", siguiendo la versión original de funciones anónimas, el cálculo lambda.[21] // El primer int es el tipo x
// El segundo int es el tipo de retorno
Func<int,int> foo = x => x*x;
Console.WriteLine(foo(7));
Mientras la función sea anónima, no se puede asignar a una variable implícitamente tipada, ya que la sintaxis lambda podría ser una función anónima o un árbol de expresiones, y la elección no puede ser realizada automáticamente por el compilador. Por ejemplo, esto no funciona: // esto NO compilará
var foo = (int x) => x*x;
Sin embargo, una expresión lambda puede tomar parte en una inferencia de tipos y puede ser utilizada como un argumento de método, Por ejemplo, para utilizar funciones anónimas con la capacidad de mapeo usando // Inicializa la lista:
var values = new List<int>() { 7, 13, 4, 9, 3 };
//Mapea las funciones anónimas sobre todos los elementos de una lista, retorna 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 junto a .NET Framework v1.0) proporcionó soporte de función anónima parcial mediante el uso de delegados. Esta construcción es similar a los delegados en PHP. En C# 1.0, los delegados son similares a punteros de funciones que hacen referencia a un método denominado explícitamente dentro de una clase. C# v2.0 (lanzado en noviembre de 2005 junto a .NET Framework v2.0) introdujo el concepto de métodos anónimos como una forma de escribir bloques de declaración sin nombre que se puedan ejecutar en una invocación delegada. C# 3.0 sigue permitiendo estas construcciones, pero también permite la construcción de expresiones lambda. El siguiente ejemplo está diseñado para ser compilado en C# 3.0 y mostrará las tres formas en las que es posible escribir un método anónimo: public class TestDriver
{
delegate int SquareDelegate(int d);
static int Square(int d)
{
return d*d;
}
static void Main(string[] args)
{
// C# 1.0: Sintaxis delegada original necesaria
// inicializando con un método nombrado
SquareDelegate A = new SquareDelegate(Square);
System.Console.WriteLine(A(3));
// C# 2.0: Un delegado puede inicializarse con
// un código en línea, llamado "método anónimo".
// Este método toma un int como un parámetro de entrada
SquareDelegate B = delegate(int d) { return d*d; };
System.Console.WriteLine(B(5));
// C# 3.0. Un delegado puede inicializarse con
// una expresión lambda. La expresión lambda toma un int y retorna otro int.
// El tipo de x es inferido por el compilador.
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 2.0 de C#, el compilador 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 recibe un nombre generado; Este nombre generado se basa en el nombre del método en el que se declara el Delegado. El nombre no está expuesto al código de la aplicación a menos que se utilice reflexión. En el caso de la versión 3.0 de C# , el mismo mecanismo es aplicado. Visual Basic .NETVisual Basic .NET 2008Visual Basic .NET 2008 introdujo las funciones anónimas a través de la estructura lambda. Combinada con la escritura de tipos implícitos, VB provee una sintaxis sencilla para escribir funciones anónimas.En VB.NET 2008 las funciones anónimas deben ser definidas en una sola línea; no pueden ser expresiones compuestas. Además, una función anónima en VB.NET debe realmente una Dim Funcion_lambda = Function(x) x * x 'Crea la función de nombre "Funcion_lambda", la cual multiplica el argumento que se le pase por sí mismo.
Console.WriteLine(Funcion_lambda(10)) 'Retorna 100 (10 x 10)
'Ya que el código no realiza una verificación del tipo de argumento que se pasa a "Funcion_lambda"
'en caso de que el tipo de argumento sea inválido, puede ocurrir una excepción en tiempo de ejecución.
Visual Basic .NET 2010Desde Visual Basic .NET 2010 se es posible definir expresiones lambda multilíneas las cuales además ya no requieren que retornen algún valor.
En el siguiente ejemplo se utiliza una función lambda multilinea para definir un Dim t As New System.Threading.Thread(Sub()
For n as Integer = 0 to 10 'Cuenta hasta 10
Console.WriteLine(n) 'Imprime cada número
Next
End Sub)
t.Start() 'Da la orden de que se ejecute el thread definido en la expresión lambda.
Es posible utilizar las expresiones lambda en VB.NET dentro de un Public Shared Variable1 As Integer
Sub Run_tasks()
For a As Integer = 0 To 9
Task.Run(Sub()
'Acá es posible realizar cualquier tarea que tome tiempo, esta se ejecuta en un thread distinto
'y no detiene el programa
System.Threading.Thread.Sleep(100) 'Espera que pasen 100 milisegundos
Variable1 = Variable1 + 1
End Sub)
Next
End Sub 'La subrutina se completa pero las tareas creadas siguen ejecutándose.
Véase también
Referencias
Enlaces externos
|