2011-11-23 9 views
5

c'è un modo per averemodo consigliato per avere 2+ moduli si riferiscono in modo ricorsivo gli uni agli altri in Lua 5.2

  • Due moduli Lua (chiamiamoli A e B)
  • Ogni modulo utilizza le funzioni dal altro, quindi devono require l'un l'altro
  • Un terzo modulo (chiamiamolo C) può utilizzare A ma non B ad es.

C.lua:

local A = require 'A' 

-- ... 

A.foo() 
  • Ci può essere un altro modulo D che richiede B ma non A e/o E richiede sia A e B
  • AB né loro membri dovrebbero essere aggiunto allo spazio dei nomi globale.
  • Evitare di utilizzare le funzioni module e setfenv (deprecato in Lua 5,2)

Related: Lua - how do I use one lib from another? (nota:. Questa soluzione non gestisce le dipendenze circolari)

risposta

5

ho trovato un bel modo semplice per farlo:

A.lua:

local A = {} 
local B 

function A.foo() 
    B = B or require 'B' 
    return B.bar() 
end 

function A.baz() 
    return 42 
end 

return A 

B.lua:

local B = {} 
local A 

function B.bar() 
    A = A or require 'A' 
    return A.baz() 
end 

return B 
+0

C'è qualche danno nel chiamare 'require' all'interno di una funzione come questa? L'ho sempre visto usato al massimo livello. – finnw

+4

Non c'è alcun avviso nel [manuale di riferimento] (http://www.lua.org/manual/5.1/manual.html#pdf-require) a riguardo, quindi penso che sia sicuro. –

+1

Puoi usare 'require' ovunque nel codice. Per esempio, spesso uso questo idioma per avviare RemDebug in un determinato punto del file: 'se la condizione richiede quindi 'remdebug.engine'.start() end' –

2

Un modo standard di fare questo in qualsiasi lingua è quello di introdurre un mediatore. I moduli possono quindi pubblicare e iscriversi al mediatore. http://en.wikipedia.org/wiki/Mediator_pattern

Un esempio di questo nelle mie lingue è mvccontrib bus, IEventAggregator e MVVM Lite Messenger. Fanno tutti la stessa cosa

3

altro metodo, proposto da Owen Shepherd the lua-l mailing list:

Se impostato package.loaded[current-module-name] nella parte superiore di ogni modulo, allora qualsiasi altro modulo require d successivamente può fare riferimento al modulo corrente (anche incompleta).

A.lua:

local A = {} 
package.loaded[...] = A 

local B = require 'B' 

function A.foo() 
    return B.bar() 
end 

function A.baz() 
    return 42 
end 

return A 

B.lua:

local B = {} 
package.loaded[...] = B 

local A = require 'A' 

function B.bar() 
    return A.baz() 
end 

return B 

Questo non funziona in tutto il mondo.Ad esempio, se l'inizializzazione di B dipende da A.baz, l'esito sarà negativo se viene caricato prima A, poiché B vedrà una versione incompleta di A in cui baz non è ancora definito.

+0

se non si desidera chiamare richiede tutto il tempo (in ogni funzione descritta da [finnw 'altra soluzione] (http://stackoverflow.com/a/8248862/1162609), sembra che questa sia l'unica via da percorrere. Imho è anche molto carino dato che il 'return modename' alla fine del tuo modulo è scritto in' package.loaded [...] '(usando questa struttura di spazio dei nomi globale non inquinante e restituendo tabelle dai moduli) –

Problemi correlati