2016-11-10 9 views
1

Я хочу, чтобы сразу требовалось несколько модулей Lua, аналогично знаку звездочки с Java (import java.awt.*). Эта структура я организовал свои модули в подкаталогах:Как потребовать несколько модулей в одном выражении?

<myapp> 
-- calculations 
    -- calc1 
    -- calc2 
    -- calc3 
-- helper 
    -- help1 
    -- help2 
    -- print 
      --graphprinter 
      --matrixprinter 

Мой клиент требует, чтобы каждый модуль подпуть:

local graphprinter = require("myapp.helper.print.graphprinter") 
local matrixprinter = require("myapp.helper.print.matrixprinter") 

Я предпочел бы автоматический мульти-требует, который получает локальные имена таблиц из путь к модулю и требует сразу всего подпути. Это может быть формат: require("myapp.helper.print.*"). Автоматически имена локальных таблиц должны быть созданы для каждого модуля подкаталога, так что нет никакой разницы, поскольку я бы требовал от них модуля по модулю.

+1

У Lua нет возможности получить список всех файлов в папке, поэтому вы не можете получить список модулей. Но вы можете написать скрипт, чтобы получить список модулей, выдав команды оболочки с помощью 'io.popen 'ls ..." ', а затем' require() 'все найденные модули. –

+1

Существует также рекомендация не создавать глобальные переменные в модулях. Таким образом, нет простого способа получить значение модуля, даже если вы можете загрузить все из них.Поэтому может быть просто отдельный файл, который загружает все необходимые значения и возвращает загруженные значения в виде таблицы. – moteus

ответ

1

Модуль envчастично достигает того, что вы ищете, хотя он далек от совершенства.

Он позволяет импортировать сгруппированные/именованные имения с некоторыми предостережениями - основной из которых - вы должны вручную управлять своей средой. Кроме того, вам нужно будет написать индексные файлы (по умолчанию init.lua, если только вы не написали пользовательский набор путей), поскольку он предназначен для использования с модулями, которые экспортируют таблицы.

Вот несколько примеров. Сначала нам нужно правильно настроить нашу файловую структуру.

-- main.lua 
-- calculations/
    -- calc1.lua 
    -- calc2.lua 
    -- calc3.lua 
    -- init.lua 
-- helper/
    -- print/
      -- init.lua 
      -- graphprinter.lua 
      -- matrixprinter.lua 

Индексные файлы, которые немного утомительно:

-- calculations/init 
return { 
    calc1 = require 'calculations.calc1', 
    calc2 = require 'calculations.calc2', 
    calc3 = require 'calculations.calc3' 
} 

и

-- helpers/print/init 
return { 
    graphprinter = require 'helper.print.graphprinter', 
    matrixprinter = require 'helper.print.matrixprinter' 
} 

Внутри основного файла. Основная оговорка проявляется быстро, вы должны использовать возвращаемую функцию, требуя, чтобы 'env' переопределил вашу локальную среду. Передача аргументов не приведет к созданию клона вашей текущей среды (сохраняя require и т. Д.).

-- main.lua 
local _ENV = require 'env'() -- (see notes below) 

Новая среда будет дана import функция, которая принимает один аргумент, строка представляет путь или имя модуля для импорта в текущих условиях. Возвращаемое значение - это временная таблица, которая может использоваться для дальнейшего изменения состояния среды.

import 'helper/print' :use '*' 
import 'calculations' :use '*' 

Одна из функций на переходной таблицы :use, который либо принимает таблицу с указанием, какие значения вытащить из требуемой таблицы или строки '*', что означает, что вы хотите все значения из таблицы требуемого помещается в текущей среде

print(matrixprinter, graphprinter) --> function: 0x{...} function: 0x{...} (or so) 

окончательный нюанс в том, что все пути, которые вы видели полагаются на cwd быть такой же, как тот, который держит main.lua. lua myapp/main.lua не удастся громко, если вы не разместите свои вспомогательные модули в статическом местоположении и правильно настройте package.path/import.paths.

Кажется, что много работы, чтобы избежать нескольких строк из require утверждений.


Отказ от ответственности: я написал env как немного эксперимента.

Обратите внимание, что import в настоящее время не поддерживает . синтаксиса (вы должны использовать OS разделитель пути), или надлежащие взрывающиеся таблицы в таблицах цепочек. У меня есть небольшой патч в работах, которые обращаются к этому.

Lua 5.2+ использует _ENV для переопределения локальных условий. Для Lua 5.1 вам нужно будет использовать setfenv.


Как уже упоминалось выше, Lua не имеет реального представления каталогов. Чтобы действительно делать то, что вы хотите (с меньшими накладными расходами), вам нужно будет написать собственный пользовательский загрузчик модулей, обработчик среды и, вероятно, использовать модуль, например LuaFileSystem, чтобы «автоматически» загружать все файлы в каталог.


TL; DR:

  • Это сложная тема.
  • В этом языке нет ничего, чтобы сделать это легко.
  • Вам нужно будет написать что-то обычай.
  • Всегда будут недостатки.
4

Почему бы вам просто не написать файл init.lua для каждой папки, требующей всех других библиотек?

Например, в расчетах вы пишете файл, содержащий

return { 
    calc1 = require "calc1"; 
    calc2 = require "calc2"; 
    calc3 = require "calc3"; 
} 

Тогда вы можете просто написать calculations = require "calculations", и он будет автоматически загружать calculations.calc<1-3>

Это может быть сделано для всей структуры каталогов и require "helper" может позвонить require "help1", который, в свою очередь, вызывает require "print", и в конце вы можете найти свои функции в: helper.help1.print.<function>

Краткое объяснение того, как это работает: при запуске require "library" lua либо попытается включить файл с именем library.lua, либо файл init.lua, расположенный в каталоге library. Это также является причиной того, что вы делаете require "dir.lib" вместо require "dir/lib"; потому что, если все сделано правильно, когда вы просто require "dir", он вернет таблицу, содержащую поле lib, поэтому вы получите доступ к ней как dir.lib.<function>.