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?

Foi útil?

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ção local 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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top