Recommended way to have 2+ modules recursively refer to each other in Lua 5.2

3.4k Views Asked by At

Is there a way to have

  • Two Lua modules (let's call them A and B)
  • Each module uses functions from the other, so they must require each other
  • A third module (let's call it C) can use A but not B e.g.

C.lua:

local A = require 'A'

-- ...

A.foo()
  • There may be another module D that requires B but not A and/or E requiring both A and B
  • Neither A nor B nor their members should be added to the global namespace.
  • Avoid using the module and setfenv functions (deprecated in Lua 5.2)

Related: Lua - how do I use one lib from another? (note: this solution does not handle circular dependencies.)

3

There are 3 best solutions below

3
On BEST ANSWER

I found quite a simple way to do it:

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
On

A standard way to do this in any language is to introduce a mediator. Modules can then publish and subscribe to the mediator. http://en.wikipedia.org/wiki/Mediator_pattern

An example of this in my languages is mvccontrib bus, IEventAggregator, and MVVM Lite Messenger class. They all do the same thing.

1
On

Another method, suggested by Owen Shepherd on the lua-l mailing list:

If we set package.loaded[current-module-name] at the top of each module, then any other module required later can refer to the current (possibly incomplete) module.

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

This will not work everywhere. For example if B's initialization depends on A.baz then it will fail if A is loaded first, because B will see an incomplete version of A in which baz is not yet defined.