如何在单个语句中要求多个模块?

时间:2016-11-10 08:04:45

标签: module lua wildcard packages require

我想一次需要几个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.*")。应该自动为子目录的每个模块创建本地表名,这样就没有任何区别,因为我会逐个模块地要求它们。

2 个答案:

答案 0 :(得分: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>访问。

答案 1 :(得分: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,它可以获取一个表来指示从所需表中提取哪些值,或者使用字符串'*',这表示您希望 all 来自当前环境中所需表格的值

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

最后一点需要注意的是,您所看到的所有路径都依赖于cwd与持有main.lua的路径相同。 lua myapp/main.lua会大声失败,除非您将子模块放在静态位置,并正确调整package.path / import.paths

似乎有很多工作要避免几行require语句。

免责声明:我写了env作为一个实验。

请注意,import目前不支持.语法(您需要使用操作系统路径分隔符),或者正确地将表格扩展到表链中。我在工作中有一些补丁来解决这个问题。

Lua 5.2+使用_ENV来覆盖本地环境。对于Lua 5.1,您需要使用setfenv

如上所述,Lua没有真正的目录概念。要真正做到你想要的(减少开销),你需要编写自己的自定义模块加载器,环境处理程序,并且可能使用像LuaFileSystem这样的模块来自动地&#39;自动&# 39;加载目录中的所有文件。

TL; DR:

  • 这是一个棘手的话题。
  • 这种语言没有任何内容可以使这一切变得简单。
  • 你需要写一些自定义的内容。
  • 总会有缺点。