第 1 版は Lua 5.0 用に記述されました。以降のバージョンでは依然として広く関連がありますが、違いがあります。
第 4 版は Lua 5.3 を対象としており、Amazon やその他の書店で入手できます。
書籍を購入することで、Lua プロジェクトをサポートすることもできます。


15.2 – プライバシー

パッケージはすべての名前を エクスポートする場合があります。つまり、パッケージのクライアントはすべてそれらを使用できます。しかし、通常はパッケージ内にプライベートな名前、つまりパッケージ自体だけが使用できる名前があることが役立ちます。Lua でそれを行う便利な方法は、プライベートな名前をローカル変数として定義することです。たとえば、有効な複素数であるかどうかを確認するプライベート関数を例に追加します。例を次に示します

    local P = {}
    complex = P
    
    local function checkComplex (c)
      if not ((type(c) == "table") and
         tonumber(c.r) and tonumber(c.i)) then
        error("bad complex number", 3)
      end
    end
    
    function P.add (c1, c2)
      checkComplex(c1);
      checkComplex(c2);
      return P.new(c1.r + c2.r, c1.i + c2.i)
    end
    
      ...
    
    return P

このアプローチの利点と欠点はどのようなものですか? パッケージ内のすべての名前は別の名前空間内にあります。パッケージ内の各エンティティは、公開または非公開として明確にマークされます。さらに、真のプライバシーがあります。プライベートエンティティには、パッケージ外部からアクセスできません。このアプローチの欠点は、同じパッケージ内の他の公開エンティティにアクセスするときに、すべてのアクセスにプレフィックス P が引き続き必要になるため、冗長になることです。さらに大きな問題は、関数のステータスをプライベートから公開 (または公開からプライベート) に変更するたびに呼び出しを変更する必要があることです。

両方の問題に対する興味深い解決策があります。パッケージ内のすべての関数をローカルとして宣言し、後でエクスポートする最後のテーブルに配置できます。このアプローチに従うと、complex パッケージは次のようになります

    local function checkComplex (c)
      if not ((type(c) == "table")
         and tonumber(c.r) and tonumber(c.i)) then
        error("bad complex number", 3)
      end
    end
    
    local function new (r, i) return {r=r, i=i} end
    
    local function add (c1, c2)
      checkComplex(c1);
      checkComplex(c2);
      return new(c1.r + c2.r, c1.i + c2.i)
    end
    
      ...
    
    complex = {
      new = new,
      add = add,
      sub = sub,
      mul = mul,
      div = div,
    }

これで、呼び出しにプレフィックスを付ける必要がなくなりました。エクスポートされた関数とプライベート関数の呼び出しは同等です。エクスポートする名前を明示的に定義するシンプルなリストが、パッケージの最後にあります。ほとんどの人は、このリストをパッケージの先頭に表示するほうが自然と感じるでしょう。しかし、最初にリストを置くことはできません。ローカル関数を最初に定義する必要があるためです。