Рекомендуемый способ рекурсивно ссылаться на 2+ модуля в Lua 5.2 - PullRequest
6 голосов
/ 24 ноября 2011

Есть ли способ иметь

  • Два модуля Lua (назовем их A и B)
  • Каждый модуль использует функции другого, поэтому они должныrequire друг друга
  • Третий модуль (назовем его C) может использовать A, но не B, например,

C.lua:

local A = require 'A'

-- ...

A.foo()
  • Может существовать другой модуль D, для которого требуется B, но не A и / или E, требующие A и B
  • Ни A ни B, ни их члены не должны добавляться в глобальное пространство имен.
  • Избегать использования функций module и setfenv (не рекомендуется в Lua 5.2)

Связано : Lua - как использовать одну библиотеку из другой? (примечание: это решение не обрабатывает циклические зависимости.)

Ответы [ 3 ]

6 голосов
/ 24 ноября 2011

Я нашел довольно простой способ сделать это:

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
3 голосов
/ 21 декабря 2012

Другой метод, предложенный Оуэном Шепардом в списке рассылки lua-l :

Если мы установим package.loaded[<em>current-module-name</em>] в верхней части каждого модуля, то любой другой модуль require d позже может ссылаться на текущий (возможно, неполный) модуль.

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

Это не будет работать везде. Например, если инициализация B зависит от A.baz, то произойдет сбой, если сначала загрузится A, поскольку B увидит неполную версию A, в которой baz еще не определена.

3 голосов
/ 07 декабря 2011

Стандартный способ сделать это на любом языке - это ввести посредника. Затем модули могут публиковать и подписываться на посредника. http://en.wikipedia.org/wiki/Mediator_pattern

Примером этого в моих языках является шина mvccontrib, IEventAggregator и класс MVVM Lite Messenger. Все они делают одно и то же.

...