この初版は Lua 5.0 向けに書かれています。後のバージョンでも将来に大きく関係がありますが、いくつかの違いがあります。
第 4 版は Lua 5.3 を対象としており、Amazon や他の書店で購入できます。
本を購入することにより、Lua プロジェクトの支援にもつながります。


15.5 – その他の機能

前述のとおり、テーブルを使用してパッケージを実装することで、Lua のすべての機能を利用してパッケージを操作できます。可能性は無限です。ここでは、推奨事項をほんの数ポイント紹介します。

パッケージのパブリックアイテムをすべて同時に定義する必要はありません。たとえば、complex パッケージに別のチャンクで新しいアイテムを追加できます。

    function complex.div (c1, c2)
      return complex.mul(c1, complex.inv(c2))
    end
(ただし、プライベート部分は 1 つのファイルに制限されることに注意してください。これは良いことだと思います。)逆に、同じファイル内に複数のパッケージを定義できます。必要なのは、それぞれのブロックを do ブロック内に囲み、ローカル変数をブロックに限定することだけです。

パッケージの外側で、いくつかの演算を頻繁に使用する場合は、ローカル名を与えることができます。

    local add, i = complex.add, complex.i
    
    c1 = add(complex.new(10, 20), i)
あるいは、パッケージ名を何度も記述したくない場合は、パッケージ自体に短いローカル名を与えることができます。
    local C = complex
    c1 = C.add(C.new(10, 20), C.i)

パッケージ内のすべての名前をグローバル名前空間に配置する関数は簡単に記述できます。

    function openpackage (ns)
      for n,v in pairs(ns) do _G[n] = v end
    end
    
    openpackage(complex)
    c1 = mul(new(10, 20), i)
パッケージを開いたときに名前の衝突を恐れる場合は、代入前に名前を確認できます。
    function openpackage (ns)
      for n,v in pairs(ns) do
        if _G[n] ~= nil then
          error("name clash: " .. n .. " is already defined")
        end
        _G[n] = v
      end
    end

パッケージ自体がテーブルであるため、パッケージをネストさせることもできます。つまり、1 つのパッケージ内で別のパッケージを作成できます。ただし、この機能はほとんど必要ありません。

もう 1 つの興味深い機能は 自動ロードです。これにより、プログラムによって実際に機能が使用されたときにのみその機能がロードされます。自動ロードパッケージをロードすると、空のテーブルがパッケージを表すために作成され、テーブルの __index メタメソッドが自動ロードを実行するように設定されます。次に、まだロードされていない関数呼び出すと、__index メタメソッドが呼び出されてロードされます。その後の呼び出しでは関数がすでにロードされているため、メタメソッドはアクティブになりません。

自動ロードを実装する簡単な方法は次のとおりです。各関数は補助ファイルで定義されます。(各ファイルには 2 つ以上の関数を含めることができます。)これらのファイルのそれぞれがここに示すように、標準的な方法で関数を定義します。

    function pack1.foo ()
      ...
    end
    
    function pack1.goo ()
      ...
    end
ただし、ファイルはパッケージを作成しません。これは、関数がロードされた時点でパッケージがすでに存在するためです。

メインパッケージ内で、各関数を検索する場所を記述する補助テーブルを定義します。

    local location = {
      foo = "/usr/local/lua/lib/pack1_1.lua",
      goo = "/usr/local/lua/lib/pack1_1.lua",
      foo1 = "/usr/local/lua/lib/pack1_2.lua",
      goo1 = "/usr/local/lua/lib/pack1_3.lua",
    }
次に、パッケージを作成し、そのメタメソッドを定義します。
    pack1 = {}
    
    setmetatable(pack1, {__index = function (t, funcname)
      local file = location[funcname]
      if not file then
        error("package pack1 does not define " .. funcname)
      end
      assert(loadfile(file))()     -- load and run definition
      return t[funcname]           -- return the function
    end})
    
    return pack1
このパッケージをロードした後、プログラムが pack1.foo() を初めて実行すると、その __index メタメソッドが呼び出されます。これは非常に簡単です。関数が対応するファイルを持っていることを確認し、そのファイルをロードします。唯一の難点は、ファイルをロードするだけでなく、アクセス結果として関数を返す必要があることです。

このシステムはすべて Lua で記述されているため、動作を変更するのは簡単です。たとえば、関数を C で定義し、メタメソッドを使用して loadlib でそれらを読み込むことができます。あるいは、グローバルトーブルにメタメソッドを設定してパッケージ全体を自動ロードすることができます。可能性は無限にあります。