Lua - 我如何动态调用一个模块?

以下是我正在使用的精简版 Lua 代码。我需要知道如何动态调用另一个模块('zebra'):

avar = require "avar"
bvar = require "bvar"

function create(zebra)
  print(zebra.new())
end

print(create(avar))

这里有两个模块:

local Avar = {}

function Avar.new()
  return "avar"
end

return Avar

local Bvar = {}

function Bvar.new()
  return "new"
end

function Bvar.old()
  return "old"
end

return Bvar

如果我尝试将字符串"avar"传递给我的'create'函数,它不起作用。如果我不带引号传递单词 'avar',它确实起作用,但是,我不明白没有引号的 avar是什么?它似乎是一个空表?不确定如何在我的主程序中将空表作为参数传递。

但也许我完全走错了。我应该如何动态调用模块?

点赞
用户90511
用户90511

avar是你创建的全局变量,不使用引号。它的初始化值是由require函数1返回的值,这个值是你调用的模块返回的值。在这种情况下,它是一个具有new字段的表,这个字段恰好是一个函数。

1 在Lua中导入模块是通过常规函数而不是特殊语法完成的。如果函数调用括号是单个参数的字符串或表,则可以省略括号,因为如果你创建了一个带有单个参数的函数调用,并且该参数是一个字符串或一个表,则括号是可选的。

除此之外,你在这里也有一些混淆的地方:

  • 你在avar中存储的表不是空的!您可以通过执行for k,v in pairs(avar) do print(k,v) end来打印其内容。

  • avarbvarcreate变量默认为全局变量,并且会被其他模块看到。大多数情况下,你更愿意将它们变成局部变量。

    local avar = -- ...
    local bvar = -- ...
    
    local function create (zebra)
      -- ...
    end
    
  • create函数显然期望一个表,因为它在它的参数上进行了表索引(获取new键并调用它)。字符串没有“new”键,因此它将无法工作。

  • 你并不真正可以动态调用一个模块。你以常规方式要求该模块,并且只是碰巧将模块返回值传递给了函数。

  • create总是返回nil,因此没有必要执行print(create(avar))。你可能想修改create以返回其对象而不是将其打印出来。

2014-01-13 04:22:28
用户869951
用户869951

你可以随时要求:

function create(zebraModuleName)
  zebraType = require(zebraModuleName)
  print(zebraType .new())
end

print(create("avar"))
print(create("bvar"))
2014-01-13 13:03:30
用户919632
用户919632

你可以使用 Lua 语言的标准 require 或者使用元表/元方法来构建自己的加载器。

1. 创建全局函数:

function dynrequire (module)
  return setmetatable ({},{
    __index = function (table,key)
      return require(module..'.'..key)
    end
  })
end

2. 创建可以在 package.path 中看到的项目树

./MySwiss/
  \___ init.lua
  \___ cut.lua
  \___ glue.lua
  \___ dosomething.lua

3. 使你的模块动态化 你只需在 MySwiss/init.lua 中加入这一行(就像将 PHP 类设置命名空间):

return dynrequire('MySwiss')

4. 要求模块并动态使用子属性 在脚本中,你只需要要求 MySwiss 和带有 dynrequire('MySwiss.SubFolderName') 的文件夹文件(或子文件夹)。

var X = require('MySwiss')
X.glue()

请注意,MySwiss 没有 glu 键。但是当你尝试访问 glu 键时,元方法 __index 会尝试要求子模块。你可以使用这种技术来获得整个项目树。唯一的缺点是外部依赖项没有以这种方式打包。

2019-08-01 04:03:35