En Lua al final
Veamos un ejemplo sencillo. Suponga que tiene una lista de nombres de estudiantes y una tabla correspondiente a los nombres y calificaciones de los estudiantes. Quiere clasificar a los estudiantes de mayor a menor según sus calificaciones, nombre = {Peter, Paul, Mary}
Calificación = {Mary = 10, Paul = 7, Peter = 8}
tabla .sort(nombre, función(n1, n2)
devuelve calificación[n 1]> calificación[n2] - compara calificaciones
Fin) Supongamos que crea una función para implementar esta función:
Función sortbygrade(nombre, calificación)
table.sort(nombre, función (n1, n2)
Devolver calificación [n 1] > ;Calificaciones[n2] - Comparando calificaciones
Fin) En el ejemplo, la función anónima contenida en sort dentro de la función sortbygrade tiene acceso a los parámetros de calificaciones de sortbygrade. En una función anónima, el resultado no es una variable global ni una variable local. La llamamos variable local externa o valor ascendente. Upvalue es algo engañoso, pero su existencia en Lua tiene raíces históricas y es más corta que las variables locales externas.
Mire el siguiente código:
Función newCounter()
Local i = 0
Función de retorno ()-función anónima
i = i + 1
Regresar I
Fin
Fin
c1 = nuevoContador()
p>print(c 1())-& gt; 1
print(c 1())-& gt; upvalue i para guardar Cuenta. Cuando llamamos a la función anónima, I está fuera de alcance porque la función newCounter que creó I ya regresó. Sin embargo, Lua maneja correctamente esta situación utilizando la idea de cierre. En pocas palabras, un cierre es una función y su límite superior. Si volvemos a llamar a newCounter, crearemos una nueva variable local I, por lo que obtendremos un nuevo cierre que actúa sobre la nueva variable I.
c2 = nuevoContador()
imprimir(C2())->1
imprimir(c 1())->tres
print(C2())->2
C1 y c2 son dos cierres diferentes, basados en la misma función, pero que actúan sobre diferentes instancias de la misma variable local.
Técnicamente, un cierre se refiere a un valor en lugar de una función, que es simplemente una declaración prototipo de un cierre; sin embargo, seguimos usando el término función para referirnos a cierres sin causar confusión;
Los cierres proporcionan funciones muy útiles en contexto, como vimos antes, y pueden usarse como argumentos para ordenar como funciones anidadas (newCounter). Este mecanismo nos permite combinar fantásticas técnicas de programación en el mundo funcional de Lua. Los cierres también se pueden utilizar en funciones de devolución de llamada. Por ejemplo, en un entorno GUI, necesita crear una serie de botones, pero la función de devolución de llamada se llama cuando el usuario presiona el botón. Las tareas que deben procesarse al presionar diferentes botones pueden ser ligeramente diferentes. En concreto, una calculadora decimal requiere 10 botones similares, uno para cada número.
Puedes crearlos usando las siguientes funciones:
FunctionNumberButton(Number)
BackButton { label = digit,
Action = Function()
p>
Agregar a mostrar(número)
Fin
}
Fin
En este ejemplo, asumimos ese Botón Es una herramienta para crear nuevos botones, la etiqueta es la etiqueta del botón y la acción es la función de devolución de llamada que se llama cuando se presiona el botón. En realidad, es un cierre porque accede a un número de valor ascendente. Después de que digitButton regresa de la tarea, el dígito de la variable local queda fuera de alcance. Aún puede llamar a la función de devolución de llamada y acceder al dígito de la variable local.
Los cierres también son útiles en un contexto completamente diferente. Debido a que las funciones se almacenan en variables ordinarias, podemos redefinir o predefinir funciones fácilmente. Por lo general, cuando necesita una nueva implementación de la función original, puede redefinir la función. Por ejemplo, puedes redefinir sin para aceptar grados en lugar de radianes como argumento:
oldSin = math.sin
math.sin = function(x)
Devolver oldSin(x*math.pi/180)
Fin
Una forma más limpia:
Hacer
local oldSin = math .sin
Local k = math.pi/180
math.sin = función (x)
Devuelve oldSin(x*k) p>
Fin
Fin
Entonces colocamos la versión original en una variable local, y la única forma de acceder a sin es a través de la nueva versión de la función.
Usando la misma característica, podemos crear un entorno seguro (también llamado sandbox, al igual que el sandbox en Java) cuando ejecutamos un fragmento de código que no es de confianza (por ejemplo, ejecutamos desde la red El código obtenido por el servidor), es necesario utilizar este entorno. Por ejemplo, podemos usar cierres para redefinir la función de apertura de la biblioteca io para limitar los archivos abiertos por el programa.
Hacer
local oldOpen = io.open
io.open = función(nombre de archivo, modo)
si acceso_OK(nombre de archivo , modo), luego
Devuelve oldOpen(nombre de archivo, modo)
Otros
Devuelve cero, acceso denegado
Fin
p>Fin en el esquema final
Otros lenguajes de programación utilizan principalmente el segundo significado de cierre (un concepto que no tiene nada que ver con el cierre): el cierre también es un proceso que utiliza variables libres para representar el proceso. Pero la palabra "cierre" en Scheme proviene del álgebra abstracta. En álgebra abstracta, se dice que un conjunto de elementos bajo una operación (operación) es cerrado. Si esta operación se aplica a un elemento de la colección, seguirá produciendo el elemento de la colección.
Tome el par de secuencias de Scheme como ejemplo. Para lograr la abstracción de datos, Scheme proporciona una estructura compuesta llamada par de secuencias. Esta estructura se puede construir mediante procesos básicos. El procedimiento cons acepta dos parámetros y devuelve un objeto de datos compuesto que contiene estos dos parámetros como componentes. Tenga en cuenta que un par ordenado también es un objeto de datos. Además, se pueden utilizar contras para construir un par de secuencias cuyos elementos sean en sí mismos pares de secuencias, y continuar haciéndolo.
(Definición x (cons 1 2)) //Construye un par de secuencias X que consta de 1 y 2.
(Definición y (cons 3 4))
(Definición z (cons x y))
El esquema puede establecer el par de secuencia de los propios elementos. La estructura de la mesa sirve como base fundamental para las herramientas de representación. A esta capacidad la llamamos propiedad de cierre de los contras. En términos generales, la operación de combinar objetos de datos satisface la propiedad de cierre, es decir, el resultado obtenido al combinar objetos de datos a través de ella se puede combinar nuevamente mediante la misma operación.
La propiedad de cierre es un factor clave en el poder de cualquier función combinatoria, porque nos permite construir una jerarquía que está formada por partes, cada una de las cuales está formada por sus partes, las cuales pueden continuar.