第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目


8.1 – require 函数

Lua 提供了一个更高级别的函数来加载和运行库,称为 require。粗略地说,requiredofile 执行相同的工作,但有两个重要的区别。首先,require 在路径中搜索文件;其次,require 控制是否已经运行过某个文件,以避免重复工作。由于这些特性,require 是 Lua 中加载库的首选函数。

require 使用的路径与典型路径略有不同。大多数程序使用路径作为目录列表,在其中搜索给定文件。然而,ANSI C(Lua 运行的抽象平台)没有目录的概念。因此,require 使用的路径是一个模式列表,每个模式都指定将虚拟文件名(require 的参数)转换为真实文件名的备选方式。更具体地说,路径中的每个组件都是一个包含可选问号的文件名。对于每个组件,require 用虚拟文件名替换每个 `?´,并检查是否存在具有该名称的文件;如果没有,则转到下一个组件。路径中的组件用分号分隔(在大多数操作系统中,分号很少用于文件名)。例如,如果路径是

    ?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua
那么调用 require"lili" 将尝试打开以下文件
    lili
    lili.lua
    c:\windows\lili
    /usr/local/lua/lili/lili.lua
require 修复的唯一内容是分号(作为组件分隔符)和问号;其他所有内容(例如目录分隔符或文件扩展名)都在路径中定义。

为了确定其路径,require 首先检查全局变量 LUA_PATH。如果 LUA_PATH 的值为字符串,则该字符串为路径。否则,require 检查环境变量 LUA_PATH。最后,如果两个检查都失败,require 使用固定路径(通常为 "?;?.lua",尽管在编译 Lua 时很容易更改该路径)。

require 的另一个主要工作是避免加载相同的文件两次。为此,它保留一个包含所有已加载文件名称的表。如果所需文件已在表中,则 require 只需返回。该表保留已加载文件的虚拟名称,而不是它们的真实名称。因此,如果您使用两个不同的虚拟名称加载相同的文件,它将被加载两次。例如,命令 require"foo" 后跟 require"foo.lua",路径为 "?;?.lua",将加载文件 foo.lua 两次。您可以通过全局变量 _LOADED 访问此控制表。使用此表,您可以检查已加载哪些文件;您还可以欺骗 require 再次运行文件。例如,在成功 require"foo" 之后,_LOADED["foo"] 将不会是 nil。如果您随后将 nil 分配给 _LOADED["foo"],则后续 require"foo" 将再次运行该文件。

组件不需要有问号;它可以是固定文件名,例如以下路径中的最后一个组件

    ?;?.lua;/usr/local/default.lua
在这种情况下,每当 require 找不到其他选项时,它将运行此固定文件。(当然,只有将固定组件作为路径中的最后一个组件才有意义。)在 require 运行块之前,它定义一个全局变量 _REQUIREDNAME,其中包含所需文件的虚拟名称。我们可以使用这些功能来扩展 require 的功能。在一个极端的例子中,我们可以将路径设置为类似于 "/usr/local/lua/newrequire.lua" 的内容,以便每次调用 require 都运行 newrequire.lua,然后它可以使用 _REQUIREDNAME 的值来实际加载所需的文件。