如何在一条语句中要求多个模块?
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' 加载所有文件在目录中。
长话短说:
- 这是一个棘手的话题。
- 语言中没有内置任何东西来简化这一切。
- 您需要编写一些自定义内容。
- 缺点总会有的
我想同时要求几个 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' 加载所有文件在目录中。
长话短说:
- 这是一个棘手的话题。
- 语言中没有内置任何东西来简化这一切。
- 您需要编写一些自定义内容。
- 缺点总会有的