El papel de los cierres (cierre o funciones anónimas) en Lua

Cierre y revalorización

Cuando Lua construye una nueva función, crea un objeto de función, que contiene el prototipo de la función en sí y las variables externas o constantes utilizadas por la función. Cuando la nueva función está dentro de una función, llamamos a este objeto Closure, la variable local de la función externa a la que se refiere se llama upvalue.

A continuación se muestra un ejemplo:

function f1(n)
    local upvalue = "hello"
    local f2 = function()
        print(upvalue .. " " .. n)
    end

    return f2
end

g1 = f1(500)
g1()
print(g1)

g2 = f1(1500)
g2()
print(g2)


$ luajit copy.lua 
$ hello 500
$ function: 0x00921ae0
$ hello 1500
$ function: 0x00926f28

Cada llamada a f1 generará una nueva función (cierre) con f2 como el prototipo de función, más dos upvalues ​​(n, upvalue). Cada nuevo cierre mantiene el mismo prototipo de función y almacena diferentes upvalues. Estrictamente En otras palabras, el cierre es un concepto dinámico, que se determina durante la fase de ejecución del programa.

Alcance del valor de upvalor

Upvalue es en realidad una variable local de la función externa del cierre, que existe en la pila de la función externa. Durante la ejecución de la función externa, el cierre accede al upvalue accediendo a la referencia de upvalue de la pila de funciones externas. El proceso de llamada de la función externa se completa. La pila de la función se borra y el valor superior también se borra. En este momento, el cierre copiará el valor superior en su propia pila de funciones para su uso. Antes de que se ejecute la función externa (o cierre) , el cierre interno y sus hijos El cierre utiliza la parte de la pila de funciones externas. Cualquier modificación afectará a todas las funciones (función externa, cierre y sus subcierre). Cuando se ejecuta la función externa, el cierre interno y su subcierre Cierres El paquete utiliza la copia del cierre interior de la función exterior, que se puede deducir por analogía con el cierre más interior. El siguiente es un ejemplo.

function f1(n)
    local upvalue = "hello"

    local f0 = function()
        local f2 = function()
            n = n * 2
            print(upvalue .. " f2 " .. n)
        end
    
        local f3 = function()
            print(upvalue .. " f3 " .. n)
        end

        print(upvalue .. " f0 " .. n)
    
        return f2, f3
    end

    g1, g2 = f0()
    g1()
    g2()

    print(upvalue .. " f1 " .. n)

    return f0
end

g0 =  f1(500)

$ luajit copy.lua 
$ hello f0 500
$ hello f2 1000
$ hello f3 1000
$ hello f1 1000

f1 es una función externa, n es su variable interna, y también es el upvalor del cierre formado por los internos f2 y f3. Cabe señalar que cada vez que ingresa f1, la variable n es diferente, y el cierre generado se comparte y se guarda Es la variable local al entrar en la función externa .

El papel de los cierres

Hay dos funciones principales de los cierres. Una es la concisión, no es necesario generar objetos cuando no están en uso y no es necesario el nombre de las funciones, y la segunda, puede capturar variables externas para formar diferentes entornos de llamada. Como se puede ver en su nombre , el cierre es La función principal es este último, es decir, puede capturar variables externas.

El siguiente ejemplo ilustra:

function f1()
    local i = 0

    return function()
        i = i + 1
        return i
    end
end

g1 = f1()
g2 = f1()

print("g1 " .. g1())
print("g1 " .. g1())

print("------------------------")

print("g2 " .. g2())
print("g2 " .. g2())

$ luajit test.lua 
> g1 1
> g1 2
> ------------------------
> g2 1
> g2 2

Cada vez que se llama a f1, se genera una variable local diferente i (el valor es el valor inicial cuando se define la función). En este momento, el cierre guardará y usará i, independientemente de otros cierres. G1 y g2 comparten una función definición Es el valor inicial de upvalue, pero el entorno de llamada es independiente.

El caso de uso más típico de esta función son los iteradores:

function f1(t)
    local i = 0
    return function()
        i = i + 1
        return t[i]
    end
end

t = {"111", "heell", 5, 6, "3333"}
for e in f1(t) do
    print(e)
end

$ luajit test.lua 
> 111
> heell
> 5
> 6
> 3333

 

Supongo que te gusta

Origin blog.csdn.net/woodengm/article/details/109764026
Recomendado
Clasificación