2016-11-10 57 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 ...”'发出shell命令,然后'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目前不支持.语法(您需要使用您的操作系统的路径分隔符),或适当爆炸表到表链。我在解决这个问题的作品中有一点补丁。

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


如上所述,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的文件或位于library目录中的文件init.lua。这也是你做require "dir.lib"而不是require "dir/lib"的原因;因为如果做得对,当你只需要require "dir"时,它将返回一个包含字段lib的表格,因此您可以将其作为​​进行访问。