Forward definir uma função em Lua?
-
06-09-2020 - |
Pergunta
Como faço para chamar uma função que precisa ser chamada acima de sua criação?Li algo sobre declarações futuras, mas o Google não está sendo útil neste caso.Qual é a sintaxe correta para isso?
Solução
Lua é uma linguagem dinâmica e funções são apenas um tipo de valor que pode ser chamado com o ()
operador.Portanto, você realmente não precisa declarar a função adiante, mas sim certificar-se de que a variável no escopo ao chamá-la é a variável que você pensa que é.
Isso não é um problema para variáveis globais contendo funções, uma vez que o ambiente global é o local padrão para procurar a resolução de um nome de variável.Para funções locais, entretanto, você precisa ter certeza de que a variável local já está no escopo no ponto léxico onde você precisa chamar o valor que ela armazena, e também ter certeza de que em tempo de execução ela realmente contém um valor que pode ser chamado .
Por exemplo, aqui está um par de funções locais mutuamente recursivas:
local a,b
a = function() return b() end
b = function() return a() end
Claro, esse também é um exemplo de uso de chamadas finais para permitir recursão infinita que não faz nada, mas o ponto aqui são as declarações.Ao declarar as variáveis com local
antes de qualquer um ter uma função armazenada nele, esses nomes são conhecidos como variáveis locais no escopo léxico do restante do exemplo.Em seguida, as duas funções são armazenadas, cada uma referente à outra variável.
Outras dicas
Você pode declarar uma função declarando seu nome antes de declarar o corpo real da função:
local func1
local func2 = function()
func1()
end
func1 = function()
--do something
end
No entanto, as declarações forward só são necessárias ao declarar funções com âmbito local.Geralmente é isso que você quer fazer, mas Lua também suporta uma sintaxe mais parecida com C, caso em que a declaração direta não é necessária:
function func2()
func1()
end
function func1()
--do something
end
Testando sob a lua incorporada no Freeswitch, a declaração direta não 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:tentativa de chamar 'fmsg' global (um valor nulo)
Reverter a ordem (duh) funciona.
Para compreender quão encaminhamento encaminhamento nos trabalhos da LUA em comparação com C, você deve entender a diferença fundamental entre a compilação C e a execução da LUA.
-
em c, referência para a frente é um mecanismo de do tempo de compilação. Assim, se você incluir um modelo de declaração para a frente em um módulo C, qualquer um do seu código a seguir empregará este modelo em compilar a chamada. Você pode ou não incluir a implementação da função no mesmo módulo, caso em que ambas as declarações devem ser semanticamente idênticas ou o compilador será errado. Como esta é uma construção de tempo de compilação, o código compilado pode ser executado em qualquer ordem.
-
em Lua, referência encaminhada é mecanismo de tempo de execução , na medida em que a função compilada gera um protótipo de função internamente dentro do código, mas isso só é acessível como uma variável de tempo de execução LUA ou valor após o Execução tem passou pela declaração criando um fechamento de Lua . Aqui a ordem de declaração dentro da fonte é imaterial. É a ordem de execução que é importante: se o fechamento ainda não tiver sido vinculado à variável, então a execução vai Exceção de "Nil Value".
Se você estiver usando um local Variável para manter o valor da função, então as regras normais de escopo locais ainda se aplicam: A declaraçãolocal
deve preceder seu uso na origem e deve estar dentro do escopo, caso contrário, o compilador compilará na referência local global ou externa errada. Tão encaminhando referência usando moradores como discutido em outra resposta funcionará, mas somente se as protas forem vinculadas a fechamentos antes que a primeira chamada seja executada
Não funciona para mim se tento chamar a função antes da definição.Estou usando este script Lua no nginx conf.
thread de entrada lua abortado:erro de execução:lua_redirect.lua:109:tentativa de chamar global 'throwErrorIfAny' (um valor nulo)
Fragmento de código -
...
throwErrorIfAny()
...
function throwErrorIfAny()
ngx.say("request not allowed")
ngx.exit(ngx.HTTP_OK)
end
Dadas algumas outras respostas que também apontaram que também não funcionou para elas, é possível que a declaração direta de Lua não funcione com outras ferramentas.
PS:Funciona bem se eu colocar a definição da função antes e depois chamá-la depois.
Se você usar OOP, poderá chamar qualquer membro da função antes de sua "definição".
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()
Saída do programa:
f1
later
f2
later