expresiones - lambda expressions c#
¿Las expresiones Lambda están cerradas en C#? (4)
¿Están las clausuras de las expresiones lambda (y hasta cierto punto, funciones anónimas)?
Mi comprensión de los cierres es que son funciones que se tratan como objetos, lo que parece ser una representación precisa de lo que hacen las funciones anónimas y las expresiones Lambda.
¿Y es correcto llamarlos cierres? Entiendo que los cierres se produjeron (o se hicieron populares) debido al dialecto de lisp, pero ¿es también un término de programación general?
¡Gracias por cualquier aclaración que puedan proporcionar!
Es "cierre" no "clojure".
Eso no es lo que es un cierre. Un cierre es básicamente una representación de una función junto con cualquier variable no local que consuma la función.
En ese sentido, las lambdas no son cierres, pero causan cierres generados por el compilador si cierran sobre cualquier variable.
Si usa ILDASM en un ensamblado que contiene una lambda que cierra algunas variables, verá en ese ensamblado una clase generada por el compilador que representa la función y las variables que se cerraron. Ese es el cierre.
Cuando tu dices
funciones que se tratan como objetos,
eso es normalmente solo "objeto de función" (en C # diríamos "delegar") y es común en la programación funcional.
La respuesta de Reed es correcta; Solo agregaría algunos detalles adicionales:
las expresiones lambda y los métodos anónimos tienen semántica de cierre; es decir, "capturan" sus variables externas y extienden la vida útil de esas variables.
función anónima es el término que usamos cuando nos referimos a una expresión lambda o un método anónimo . Sí, eso es confuso. Lo siento. Fue lo mejor que se nos ocurrió.
una función que puede tratarse como un objeto es solo un delegado. Lo que hace que una lambda sea un cierre es que captura sus variables externas.
Las expresiones lambda convertidas en árboles de expresión también tienen semántica de cierre, curiosamente. ¡Y aplicar eso correctamente fue un dolor en el cuello, te lo digo!
"esto" se considera una "variable externa" con el fin de crear un cierre a pesar de que "esto" no es una variable.
Sí. Los cierres generalmente capturan variables del alcance externo. Lambdas puede hacer eso. Sin embargo, si tu lambda no captura nada, no es un cierre.
Una lambda puede implementarse utilizando un cierre, pero no es necesariamente un cierre.
Un closure es "una función junto con un entorno de referencia para las variables no locales de esa función".
Cuando crea una expresión lambda que usa variables definidas fuera del método, la lambda debe implementarse utilizando un cierre. Por ejemplo:
int i = 42;
Action lambda = () => { Console.WriteLine(i); };
En este caso, el método generado por el compilador debe tener acceso a la variable ( i
) definida en un alcance completamente diferente. Para que esto funcione, el método que genera es una "función junto con el entorno de referencia"; básicamente, está creando un "cierre" para recuperar el acceso a la variable.
Sin embargo, esta lambda:
Action lambda2 = () => { Console.WriteLine("Foo"); }
no se basa en ningún "entorno de referencia", ya que es un método totalmente contenido. En este caso, el compilador genera un método estático normal, y no hay ningún cierre involucrado en absoluto.
En ambos casos, la lambda está creando un delegate
("objeto de función"), pero solo está creando un cierre en el primer caso, ya que la lambda no necesariamente necesita "capturar" el entorno de referencia en todos los casos.