此 LTN 依賴於 Lua 5.0 中推出的「loadfile」
Lua 4.1 推出了「require」函式,用於載入和執行檔案,除非該檔案已載入。Lua 5.0 在其基礎函式庫中提供 require 作為內建函式。require 指令搭配 LTN 7「模組和套件」,為 Lua 中的簡單模組支援提供基礎。此技術備忘提出 require 的改良版本,稱為「import」。建議的 import 架構避免直接存取全域變數,修正與全域變數相關的安全漏洞,並優雅地處理循環模組相依性。
import 函式可以使用以下 Lua 5.0 程式碼實作
local imported = {} local function package_stub(name) local stub = {} local stub_meta = { __index = function(_, index) error(string.format("member `%s' is accessed before package `%s' is fully imported", index, name)) end, __newindex = function(_, index, _) error(string.format("member `%s' is assigned a value before package `%s' is fully imported", index, name)) end, } setmetatable(stub, stub_meta) return stub end local function locate(name) local path = LUA_PATH if type(path) ~= "string" then path = os.getenv "LUA_PATH" or "./?.lua" end for path in string.gfind(path, "[^;]+") do path = string.gsub(path, "?", name) local chunk = loadfile(path) if chunk then return chunk, path end end return nil, path end function import(name) local package = imported[name] if package then return package end local chunk, path = locate(name) if not chunk then error(string.format("could not locate package `%s' in `%s'", name, path)) end package = package_stub(name) imported[name] = package setglobals(chunk, getglobals(2)) chunk = chunk() setmetatable(package, nil) if type(chunk) == "function" then chunk(package, name, path) end return package end
import 的典型用法如下
-- import the complex package local complex = import "complex" -- complex now holds the public interface local x = 5 + 3*complex.I
一個套件的結構應如下
-- first import all other required packages. local a = import "a" local b = import "b" -- then define the package install function. -- the PIF more or less contains the code of a -- LTN 7 package. local function pif(Public, path) local Private = {} function Public.fun() -- public function end -- etc. end -- return the package install function return pif
Import 幾乎與 require 向後相容。不過,import 在載入期間不會定義 _REQUIREDNAME 全域變數。不會傳回 PIF 的「舊式」套件仍會載入並執行,但 import 會傳回一個空的公開介面。這不會影響舊式程式碼,因為 require 沒有傳回值。
以下是兩個套件互相匯入的範例。由於在匯入期間,兩者都不會實際使用對方,因此這不會造成問題。
套件「a.lua
」
local b = import "b" local function pif(pub, name, path) function pub.show() -- use a message from package b print("in " .. name .. ": " .. b.message) end pub.message = "this is package " .. name .. " at " .. path end return pif
套件「b.lua
」
local a = import "a" local function pif(pub, name, path) function pub.show() -- use a message from package a print("in " .. name .. ": " .. a.message) end pub.message = "this is package " .. name .. " at " .. path end return pif
以及匯入並執行兩者的程式碼
local a = import "a" local b = import "b" a.show() -- prints "in a: this is package b at ./b.lua" b.show() -- prints "in b: this is package a at ./a.lua"