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

How to require multiple modules in a single statement?

我想同时要求几个 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")

我更喜欢自动多重要求,它从模块路径派生本地 table 名称,并且一次需要一个完整的子路径。这可能是格式:require("myapp.helper.print.*")。应该自动为子目录的每个模块创建本地 table 名称,这样就没有任何区别,因为我会逐个模块地要求它们。

为什么不为每个需要所有其他库的文件夹编写一个 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",最后您可以在 [=17] 中找到您的函数=]

这是如何工作的简短说明:当您 运行 require "library" lua 将尝试包含名为 library.lua 的文件或文件 init.lua位于 library 目录中。这也是你做 require "dir.lib" 而不是 require "dir/lib" 的原因;因为,如果做得对,当你只是 require "dir" 时,它会 return 一个包含字段 lib 的 table,所以你会以 dir.lib.<function> 的形式访问它。

模块 env 部分 实现了您正在寻找的东西,尽管它远非完美。

它允许分组/命名导入,但有一些注意事项 - 主要是您必须手动管理您的环境。此外,您需要编写索引文件(默认 init.lua,除非您编写自定义路径集),因为它旨在与导出 tables.

的模块一起使用

这里有一些例子。首先我们需要正确设置我们的文件结构。

 -- 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'
}

在你的主文件中。主要警告很快就会显现出来,您必须使用函数 returned 要求 'env' 来覆盖您的本地环境。不传递参数将创建当前环境的克隆(保留 require,等等)。

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

新环境将被赋予一个import函数,它接受一个参数,一个字符串代表路径模块名称导入到当前环境。 return 值是一个瞬态值 table,可用于进一步改变环境状态。

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

瞬态 table 上的一个函数是 :use,它采用 table 指示从所需的 table 中提取哪些值,或者使用字符串'*',这表示您希望将所需 table 中的 所有 值放入当前环境

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

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

似乎需要做很多工作才能避免几行 require 语句。


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

请注意,import 目前不支持 . 语法(您需要使用 OS 路径分隔符),或 [=103 的正确分解=]s 进入 table 链。我在作品中有一些补丁可以解决这个问题。

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


如上所述,Lua 没有真正的目录概念。要真正做你想做的事(以更少的开销),你需要编写你自己的自定义模块加载器、环境处理程序,并且可能使用像 LuaFileSystem 这样的模块来可靠地 'automatically' 加载所有文件在目录中。


长话短说:

  • 这是一个棘手的话题。
  • 语言中没有内置任何东西来简化这一切。
  • 您需要编写一些自定义内容。
  • 缺点总会有的