この第 1 版は Lua 5.0 向けに執筆されました。後続のバージョンでもまだ大部分が関連していますが、いくつかの相違点があります。
第 4 版は Lua 5.3 を対象としており、Amazon やその他の書店で購入できます。
本を購入することで、Lua プロジェクトのサポートにも貢献できます。
![]() |
Lua でのプログラミングLua | ![]() |
パート II. テーブルとオブジェクト 第 15 章. パッケージ |
パッケージを作成するためのこれらすべてのメソッドの欠点は、プログラマ側の特別な注意を要することです。たとえば、宣言時に local を忘れるのはよくあることです。グローバル変数のテーブル内のメタメソッドは、パッケージを作成するための非常に興味深い代替手法を提供します。これらすべての技術の共通点は、パッケージ用の排他的な環境を使用することです。これは簡単に実行できます。パッケージのメインチャンクの環境を変更すると、そのチャンクが作成するすべての関数は、この新しい環境を共有します。
最も単純な手法はそれ以上のことではありません。パッケージに排他的な環境が用意されたら、すべての関数はこのテーブルを共有するだけでなく、そのグローバル変数もすべてこのテーブルに移動されます。したがって、すべての公開関数をグローバル変数として宣言できます。すると、自動的に別のテーブルに移動されます。パッケージが行う必要のあるのは、このテーブルをパッケージ名として登録することだけです。次のコードフラグメントは、complex
ライブラリに関するこの技術を示しています。
local P = {} complex = P setfenv(1, P)これで、関数
add
を宣言すると、complex.add
に移動しますfunction add (c1, c2) return new(c1.r + c2.r, c1.i + c2.i) endさらに、接頭辞なしでこのパッケージから他の関数も呼び出すことができます。たとえば、
add
は new
をその環境から取得します。つまり、complex.new
を取得します。この方法はパッケージに優れたサポートを提供し、プログラマーの余分な作業はほとんど必要ありません。接頭辞はまったく必要ありません。エクスポートされた関数とプライベート関数の呼び出しには違いがありません。プログラマーが local
を忘れた場合、グローバル名前空間が汚染されることはありません。代わりに、プライベート関数のみが公開されます。さらに、前のセクションの手法と組み合わせてパッケージ名に使用できます
local P = {} -- package if _REQUIREDNAME == nil then complex = P else _G[_REQUIREDNAME] = P end setfenv(1, P)
もちろん、欠けているのは他のパッケージへのアクセスです。空のテーブル P
を環境にすると、それ以前のグローバル変数にはアクセスできなくなります。これにはいくつかの解決策があり、それぞれに長所と短所があります。
最も単純な解決策は、前に見たように継承することです
local P = {} -- package setmetatable(P, {__index = _G}) setfenv(1, P)(
setfenv
を呼び出す前に setmetatable
を呼び出す必要があります。その理由はわかりますか?) この構造を使用すると、パッケージは任意のグローバル識別子に直接アクセスできますが、アクセスごとにわずかなオーバーヘッドが支払われます。この解決策の興味深い結果として、概念的には、パッケージにはすべてのグローバル変数が含まれるようになりました。たとえば、パッケージを使用する人が標準のサイン関数を呼び出す場合、complex.math.sin(x)
と記述する可能性があります。(Perl のパッケージシステムにもこの癖があります。)他のパッケージにアクセスするもう 1 つの簡単な方法は、古い環境を保持する local を宣言することです
local P = {} pack = P local _G = _G setfenv(1, P)外部の名前へのアクセスに
_G.
をプレフィックスとして指定する必要がありますが、メタメソッドに関与しないため、より高速にアクセスできます。継承とは異なり、この方法では以前の環境への書き込みアクセスを行うことができます。これが良いことか悪いことかは議論の余地がありますが、柔軟性が必要になる場合があります。より厳密なアプローチは、ローカルとして必要な関数のみ、または必要に応じてパッケージのみを宣言することです。
local P = {} pack = P -- Import Section: -- declare everything this package needs from outside local sqrt = math.sqrt local io = io -- no more external access after this point setfenv(1, P)この手法ではより多くの作業が必要になりますが、パッケージの依存関係がさらに詳しくドキュメント化されます。また、以前のスキーマよりも高速なコードになります。
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. | ![]() |