この第 1 版は Lua 5.0用に執筆されました。後続のバージョンでもほとんどが関連していますが、いくつかの違いがあります。
第 4 版は Lua 5.3を対象としており、Amazonやその他の書店で購入できます。
書籍を購入することで、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 章で説明します。

もう 1 つの方法は、メタテーブルをメモ化して、デフォルト値が同じテーブルに対して同じメタテーブルを再利用することです。ただし、そのためには弱いテーブルも必要となるため、やはり第 17 章まで待つ必要があります。