この第1版はLua 5.0用に書かれました。後続のバージョンと依然として大きく関連しますが、いくつかの違いがあります。
第4版はLua 5.3をターゲットにしており、Amazonおよびその他の本屋で入手できます。
この本を購入することで、Luaプロジェクトをサポートすることにもなります。
![]() |
LuaでのプログラミングLua | ![]() |
第2部 テーブルとオブジェクト 第14章 環境 |
Luaのグローバル変数は、宣言する必要がありません。これは小規模なプログラムにとっては便利ですが、大規模なプログラムでは簡単なタイプミスが発見の難しいバグを引き起こす可能性があります。ただし、必要に応じてその動作を変更できます。Luaはグローバル変数を通常のテーブルに保持するため、グローバル変数にアクセスするときにその振る舞いを変更するためにメタテーブルを使用できます。
最初の方法は次のとおりです
setmetatable(_G, { __newindex = function (_, n) error("attempt to write to undeclared variable "..n, 2) end, __index = function (_, n) error("attempt to read undeclared variable "..n, 2) end, })そのコードの後で、存在しないグローバル変数にアクセスしようとすると、エラーが発生します
> a = 1 stdin:1: attempt to write to undeclared variable a
しかし、新しい変数をどのように宣言するのでしょうか?メタメソッドをバイパスする「rawset」を使用して
function declare (name, initval) rawset(_G, name, initval or false) endfalseを使ったorは、新しいグローバル変数が常にnilとは異なる値を取得することを保証します。アクセス制御をインストールする前にこの関数を定義する必要があることに注意してください。そうでないとエラーが発生します。結局のところ、新しいグローバル変数「declare」を作成しようとしています。その関数を配置すると、グローバル変数を完全に制御できます
> a = 1 stdin:1: attempt to write to undeclared variable a > declare"a" > a = 1 -- OK
しかし、次に、変数が存在するかどうかをテストするために、単にnilと比較することはできません。それがnilの場合、アクセスによりエラーが発生します。代わりに、メタメソッドを回避する「rawget」を使用します
if rawget(_G, var) == nil then -- `var' is undeclared ... end
その制御を変更してnil値を持つグローバル変数を許可するのは難しくありません。必要なのは、宣言された変数の名前を保持する補助テーブルだけです。メタメソッドが呼び出されるたびに、そのテーブルで変数が宣言されているかどうかが確認されます。コードは次のようになります
local declaredNames = {} function declare (name, initval) rawset(_G, name, initval) declaredNames[name] = true end setmetatable(_G, { __newindex = function (t, n, v) if not declaredNames[n] then error("attempt to write to undeclared var. "..n, 2) else rawset(t, n, v) -- do the actual set end end, __index = function (_, n) if not declaredNames[n] then error("attempt to read undeclared var. "..n, 2) else return nil end end, })
どちらのソリューションにとっても、オーバーヘッドは無視できます。最初のソリューションでは、正常な動作中にメタメソッドが呼び出されることはありません。2番目のソリューションでは、メタメソッドが呼び出される場合がありますが、プログラムがnilを保持する変数にアクセスした場合のみです。
Copyright © 2003–2004 Roberto Ierusalimschy。全著作権所有。 | ![]() |