El cálculo lambda es un modelo informático inventado por Alonzo Church en los años 30. La sintaxis y la semántica de la mayoría de los lenguajes de programación funcionales se inspiran directa o indirectamente en el cálculo lambda.
El cálculo lambda en su forma más básica tiene dos operaciones: abstracción (crear una función (anónima)) y aplicación (aplicar una función). La abstracción se realiza utilizando el operador λ, dando nombre al cálculo lambda.
- Expresiones lambda
- Funciones lambda
Las funciones anónimas a menudo se llaman "lambdas", "funciones lambda" o "expresiones lambda" porque, como dije anteriormente, λ era el símbolo para crear funciones anónimas en el cálculo lambda (y la palabra lambda
se usa para crear funciones anónimas en muchos lisp). basados en idiomas por la misma razón).
Este no es un término de uso común, pero supongo que significa programar usando funciones anónimas o programar usando funciones de orden superior.
Un poco más de información sobre lambdas en C ++ 0x, su motivación y cómo se relacionan con los punteros de función (mucha de esto es probablemente una repetición de lo que ya sabe, pero espero que ayude a explicar la motivación de lambdas y cómo difieren). de punteros de función):
Los punteros de función, que ya existían en C, son bastante útiles para, por ejemplo, pasar una función de comparación a una función de clasificación. Sin embargo, hay límites para su utilidad:
Por ejemplo, si desea ordenar un vector de vectores por el i
elemento th de cada vector (donde i
es un parámetro de tiempo de ejecución), no puede resolver esto con un puntero de función. Una función que compara dos vectores por su i
elemento th, necesitaría tomar tres argumentos ( i
y los dos vectores), pero la función de clasificación necesitaría una función que tome dos argumentos. Lo que necesitaríamos es una forma de proporcionar de alguna manera el argumento i
a la función antes de pasarla a la función de clasificación, pero no podemos hacer esto con funciones simples de C.
Para resolver esto, C ++ introdujo el concepto de "objetos de función" o "functores". Un functor es básicamente un objeto que tiene un operator()
método. Ahora podemos definir una clase CompareByIthElement
, que toma el argumento i
como un argumento constructor y luego toma los dos vectores para compararlos como argumentos del operator()
método. Para ordenar un vector de vectores por el i
elemento th ahora podemos crear un CompareByIthElement
objeto con i
un argumento y luego pasar ese objeto a la función de clasificación.
Dado que los objetos de función son solo objetos y no técnicamente funciones (aunque están destinados a comportarse como ellos), no puede hacer que un puntero de función apunte a un objeto de función (por supuesto, puede tener un puntero a un objeto de función, pero tendría un tipo como CompareByIthElement*
y, por lo tanto, no sería un puntero de función).
La mayoría de las funciones en la biblioteca estándar de C ++ que toman las funciones como argumentos se definen usando plantillas para que funcionen con punteros de función y objetos de función.
Ahora a lambdas:
Definir una clase completa para comparar por el i
elemento th es un poco detallado si solo lo va a usar una vez para ordenar un vector. Incluso en el caso de que solo necesite un puntero de función, la definición de una función con nombre es subóptima si solo se usa una vez porque a) contamina el espacio de nombres yb) la función generalmente será muy pequeña y no hay realmente una buena razón para abstraer la lógica en su propia función (aparte de eso no puede tener punteros de función sin definir una función).
Entonces para arreglar esto se introdujeron lambdas. Las lambdas son objetos de función, no punteros de función. Si utiliza un literal lambda [x1, x2](y1,y2){bla}
, se genera un código similar que básicamente hace lo siguiente:
- Defina una clase que tenga dos variables miembro (
x1
y x2
) y una operator()
con los argumentos ( y1
y y2
) y el cuerpo bla
.
- Cree una instancia de la clase, estableciendo las variables miembro
x1
y x2
los valores de las variables x1
y x2
actualmente en el alcance.
Por lo tanto, las lambdas se comportan como objetos de función, excepto que no puede acceder a la clase que se genera para implementar una lambda de otra manera que no sea el uso de la lambda. En consecuencia, cualquier función que acepte functores como argumentos (que básicamente significa cualquier función que no sea C en la biblioteca estándar) aceptará lambdas, pero cualquier función que solo acepte punteros de función no lo hará.