porque - ¿Adelante definir una función en lua?
porque aprender lua (6)
Al realizar una prueba bajo la lua incorporada en Freeswitch, la declaración hacia adelante no funciona:
fmsg("CRIT", "It worked.")
function fmsg(infotype, msg)
freeswitch.consoleLog(infotype, msg .. "/n")
end
resultado:
[ERR] mod_lua.cpp: 203 /usr/local/freeswitch/scripts/foo.lua:1: intento de llamar global ''fmsg'' (un valor nulo)
Invertir la orden funciona (duh).
¿Cómo llamo a una función que necesita ser llamada desde arriba de su creación? Leí algo sobre las declaraciones de reenvío, pero Google no está ayudando en este caso. ¿Cuál es la sintaxis correcta para esto?
No funciona para mí si intento llamar a la función antes de la definición. Estoy usando este script Lua en nginx conf.
subproceso de entrada de lua abortado: error en tiempo de ejecución: lua_redirect.lua: 109: intento de llamar global ''throwErrorIfAny'' (un valor nulo)
Fragmento de código -
...
throwErrorIfAny()
...
function throwErrorIfAny()
ngx.say("request not allowed")
ngx.exit(ngx.HTTP_OK)
end
Dadas algunas otras respuestas también han señalado que tampoco funcionó para ellos, es posible que la declaración de Lua no funcione con otras herramientas.
PS: Funciona bien si pongo la definición de la función antes y luego la llamo después de las salas.
Para comprender cómo funciona la referencia hacia adelante en Lua en comparación con C, debe comprender la diferencia fundamental entre la compilación de C y la ejecución de Lua.
En C, la referencia hacia adelante es un mecanismo de tiempo de compilación . Por lo tanto, si incluye una plantilla de declaración de reenvío en un módulo C, cualquiera de los siguientes códigos empleará esta plantilla para compilar la llamada. Puede o no incluir la implementación de la función en el mismo módulo, en cuyo caso ambas declaraciones deben ser semánticamente idénticas o el compilador generará un error. Dado que se trata de una construcción de tiempo de compilación, el código compilado se puede ejecutar en cualquier orden.
En Lua, la referencia directa es un mecanismo de tiempo de ejecución , ya que la función compilada genera un prototipo de función internamente dentro del código, pero esto solo es accesible como una variable o valor Lua de tiempo de ejecución una vez que la ejecución ha pasado la declaración que crea un cierre Lua. Aquí el orden de declaración dentro de la fuente es inmaterial. Lo importante es el orden de ejecución: si el cierre no se ha vinculado a la variable, la ejecución arrojará una excepción de "valor nulo".
Si está usando una variable local para mantener el valor de la función, entonces las reglas de alcance locales normales todavía se aplican: la declaraciónlocal
debe preceder a su uso en la fuente y debe estar dentro del alcance, de lo contrario el compilador compilará en la referencia local externa global o incorrecta. . Por lo tanto, las referencias hacia adelante utilizando los locales como se explica en otra respuesta funcionarán, pero solo si los Protos están sujetos a cierres antes de que se ejecute la primera llamada .
Puede reenviar declarar una función declarando su nombre antes de declarar el cuerpo de la función real:
local func1
local func2 = function()
func1()
end
func1 = function()
--do something
end
Sin embargo, las declaraciones en adelante solo son necesarias cuando se declaran funciones con alcance local. Eso es lo que generalmente se quiere hacer, pero Lua también admite una sintaxis más parecida a C, en cuyo caso no es necesaria la declaración de reenvío:
function func2()
func1()
end
function func1()
--do something
end
Si usa OOP, puede llamar a cualquier miembro de la función antes de su "definición".
local myClass = {}
local myClass_mt = { __index = myClass }
local function f1 (self)
print("f1")
self:later() --not yet "delared" local function
end
local function f2 (self)
print("f2")
self:later() --not yet "declared" local function
end
--...
--later in your source declare the "later" function:
local function later (self)
print("later")
end
function myClass.new() -- constructor
local this = {}
this = {
f1 = f1,
f2 = f2,
later = later, --you can access the "later" function through "self"
}
setmetatable(this, myClass_mt)
return this
end
local instance = myClass.new()
instance:f1()
instance:f2()
Salida del programa:
f1
later
f2
later
Lua es un lenguaje dinámico y las funciones son solo un tipo de valor que se puede llamar con el operador ()
. Por lo tanto, realmente no necesita reenviar la función tanto como asegurarse de que la variable en el alcance cuando la llame es la variable que cree que es.
Esto no es un problema en absoluto para las variables globales que contienen funciones, ya que el entorno global es el lugar predeterminado donde buscar para resolver un nombre de variable. Sin embargo, para las funciones locales, debe asegurarse de que la variable local ya esté dentro del alcance en el punto léxico en el que necesita llamar el valor que almacena, y también asegurarse de que en el tiempo de ejecución realmente tenga un valor que pueda llamarse .
Por ejemplo, aquí hay un par de funciones locales recursivas:
local a,b
a = function() return b() end
b = function() return a() end
Por supuesto, este es también un ejemplo del uso de llamadas de cola para permitir una recursión infinita que no hace nada, pero el punto aquí son las declaraciones. Al declarar las variables con local
antes de que cualquiera de ellas tenga una función almacenada, se sabe que esos nombres son variables locales en el ámbito léxico del resto del ejemplo. Luego se almacenan las dos funciones, cada una de las cuales se refiere a la otra variable.