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


13.4.3 – 带有默认值的表

常规表中任何字段的默认值都是 nil。使用元表可以轻松更改此默认值

    function setDefault (t, d)
      local mt = {__index = function () return d end}
      setmetatable(t, mt)
    end
    
    tab = {x=10, y=20}
    print(tab.x, tab.z)     --> 10   nil
    setDefault(tab, 0)
    print(tab.x, tab.z)     --> 10   0
现在,每当我们访问 tab 中不存在的字段时,都会调用其 __index 元方法并返回零,这是该元方法的 d 的值。

setDefault 函数为每个需要默认值的表创建一个新的元表。如果我们有许多需要默认值的表,这可能会很昂贵。但是,元表将默认值 d 连接到自身,因此该函数不能对所有表使用单个元表。为了允许对具有不同默认值的表使用单个元表,我们可以使用一个独占字段将每个表的默认值存储在表本身中。如果我们不担心名称冲突,则可以使用像 "___" 这样的键作为我们的独占字段

    local mt = {__index = function (t) return t.___ end}
    function setDefault (t, d)
      t.___ = d
      setmetatable(t, mt)
    end
如果我们担心名称冲突,则很容易确保此特殊键的唯一性。我们只需要创建一个新表并将其用作键
    local key = {}    -- unique key
    local mt = {__index = function (t) return t[key] end}
    function setDefault (t, d)
      t[key] = d
      setmetatable(t, mt)
    end

将每个表与其默认值关联的另一种方法是使用一个单独的表,其中索引是表,而值是它们的默认值。但是,为了正确实现此方法,我们需要一种特殊类型的表,称为弱表,因此我们不会在这里使用它;我们将在 第 17 章 中回到这个主题。

另一种选择是记忆元表,以便对具有相同默认值的表重用相同的元表。但是,这也需要弱表,因此我们不得不等到 第 17 章