2011-05-20 11 views
17

Come si chiama una funzione che deve essere richiamata da sopra la sua creazione? Ho letto qualcosa sulle dichiarazioni anticipate, ma Google non è di aiuto in questo caso. Qual è la sintassi corretta per questo?Inoltra definire una funzione in Lua?

Grazie.

risposta

29

Lua è un linguaggio dinamico e le funzioni sono solo un tipo di valore che può essere chiamato con l'operatore (). Quindi non hai davvero bisogno di inoltrare la funzione dichiarare così tanto che assicurati che la variabile di scope quando la chiami sia la variabile che pensi sia.

Questo non è affatto un problema per le variabili globali che contengono funzioni, poiché l'ambiente globale è il luogo predefinito in cui cercare di risolvere un nome di variabile. Per le funzioni locali, tuttavia, è necessario assicurarsi che la variabile locale sia già in ambito nel punto lessicale in cui è necessario chiamare il valore memorizzato e assicurarsi inoltre che in fase di esecuzione sia effettivamente in possesso di un valore che può essere chiamato .

Ad esempio, ecco una coppia di funzioni locali mutuamente ricorsive:

local a,b 
a = function() return b() end 
b = function() return a() end 

Naturalmente, che è anche un esempio di utilizzo coda chiamate a consentire ricorsione infinita che non fa nulla, ma il punto qui è il dichiarazioni. Dichiarando le variabili con local prima di avere una funzione memorizzata in esso, tali nomi sono noti per essere variabili locali in ambito lessicale del resto dell'esempio. Quindi vengono memorizzate le due funzioni, ciascuna riferita all'altra variabile.

+1

Ok, grazie. Sono riuscito a capirlo da solo, ma questa risposta è stata comunque utile. –

9

È possibile inoltrare dichiarare una funzione dichiarando il suo nome prima di dichiarare il corpo della funzione attuale:

local func1 
local func2 = function() 
    func1() 
end 
func1 = function() 
    --do something 
end 

Tuttavia avanti dichiarazioni sono necessarie solo quando si dichiara funzioni con l'ambito locale. Questo è in genere ciò che si vuole fare, ma Lua supporta anche una sintassi più simile a C, nel qual caso la dichiarazione in avanti non è necessaria:

function func2() 
    func1() 
end 
function func1() 
    --do something 
end 
+4

In realtà, il tuo primo esempio non fa quello che tu pensi che funzioni dal momento che il secondo 'func1' locale sta dichiarando una * nuova * variabile di quel nome e lascia il primo' func1' orfano e ancora impostato su 'nil'. – RBerteig

+0

oops buon punto, correggerò che – jhocking

+1

Anche il tuo secondo esempio è negativo, perché l'ingenuità di chiamare "func2" da sotto func1 funzionerebbe, ma non a causa di alcun tipo di "forward statement". Piuttosto, func1 è dichiarata nell'ambiente globale (_G), e quando func2 cerca func1, controlla _G. Ciò significa che func1 viene dichiarato prima che func2 venga eseguito e quindi quando controlla _G, funziona. Lanciare una chiamata a func2 immediatamente dopo la definizione di func2 genera un errore ... perché func1 non è dichiarato/definito. – LuaWeaver

0

Test sotto la lua incorporato in Freeswitch, dichiarazione anticipata non funziona:

fmsg("CRIT", "It worked.") 
function fmsg(infotype, msg) 
    freeswitch.consoleLog(infotype, msg .. "\n") 
end 

risultato:

[ERR] mod_lua.cpp: 203 /usr/local/freeswitch/scripts/foo.lua:1: tentativo di chiamata 'FMSG' globale (un valore nullo)

L'inversione dell'ordine funziona (duh).

0

Non funziona per me se provo a chiamare la funzione prima della definizione. Sto usando questo script Lua in nginx conf.

lua entry thread aborted: runtime error: lua_redirect.lua:109: attempt to call global 'throwErrorIfAny' (a nil value)

Codice frammento -

... 
throwErrorIfAny() 
... 

function throwErrorIfAny() 
    ngx.say("request not allowed") 
    ngx.exit(ngx.HTTP_OK) 
end 

dato alcune altre risposte hanno anche sottolineato che non ha funzionato per loro sia, è possibile che dichiarazione anticipata di Lua non funziona con altri strumenti .

PS: Funziona bene se prima ho impostato la definizione della funzione e poi la chiamiamo dopo i reparti.