私はこれまでこの問題をグーグルで調べてきましたが、役に立たなかったので、誰かが答えを知っているのではないかと思っていました-luaでnil値にインデックスを付けると、スクリプトはエラーを発生させます-「変数名」にインデックスを付けようとしています-nil値-それですか代わりに、メタメソッドである可能性があることをキャプチャして、何らかの処理を行い、エラーを出さないことは可能ですか? たとえば、変数 'num' が定義されていない場合に 'num = 2' と指定すると、__newindex メタメソッドを設定して何らかの処理を行うことができ、変数名 - 'num' と値 - '2' の両方がスタック上にあることになります。しかし、'num[2] = 3' で 'num' が定義されていない場合、エラーが発生します。代わりに、__newindex と同じように、そのイベントをキャプチャして、nil 変数の名前 ('num') にアクセスしたいと考えています。インデックス - 2、および設定値 - 3.任意の助けをいただければ幸いです。
2 に答える
まず、解決しようとしている問題を説明すると、助けやすくなります。初期化されていないグローバルが使用されないようにしようとしていますか? メタテーブルでそれを行うことができます。スクリプト エラーがアプリに浸透しないようにしていますか? でそれを行うことができますpcall
。nil
グローバルのこの特定の使用法をキャッチして、何らかの方法でそれを回復しようとしているだけですか? より多くのコンテキストを提供すればするほど、他の人があなたが考えもしなかった解決策を見つけやすくなります。
num[index]
あなたが説明した状況については、どこがどこであるかをキャッチしたいのですnum
がnil
、それを直接検出することはできません。
これには 2 つの部分があります。
- の現在の値が
num
現在の環境テーブル (別名 _ENV または _G) から読み取られるとき - その値にインデックスを付けようとしたとき。
#2nil
はテーブルではないため、メタテーブルを指定できないため、検出する方法はありません。
ただし、#1を検出できます。要件によっては、#1 を使用してプロキシ オブジェクトを返すことができnil
ます。これにより、#2 を検出できるようになりますが、これはグローバルが存在しないことを意味するため、次のようなロジックは機能しません。
--- initialize globalFoo if it doesn't exists
if not globalFoo then
globalFoo = CreateGlobalFoo()
....
もちろん、 name your proxy objectNIL
のようなことはいつでもできるので、次のように書くことができます:
if globalFoo == NIL then -- globalFoo is not initilalize
globalFoo = CreateGlobalFoo()
そのように機能するプロキシ オブジェクトの例:
local nil_proxy_mt = {
__index = function(t,k) print('Attempted to index nil!') end,
__newindex = function(t,k,v) print('Attempted to index nil!') end,
}
local NIL = setmetatable({}, nil_proxy_mt)
setmetatable (_G, { __index = function(t,k) return NIL end })
これを使用して、次のいずれかを試した場合:
foo = num[2]
num[2] = 15
「Attempted to index nil!」が表示されます。プログラムは引き続き実行されます。
グローバル テーブルの __newindex メタメソッドをオーバーライドできます。
function OnNewIndex(tbl, key, value)
if tbl[key] == nil then
print(tostring(key).. " doesn't exist.")
end
end
setmetatable(_G, { __newindex = OnNewIndex })
num = 15
ただし、デフォルトでは、lua にこの動作があるとは思えません。次のようなことをするだけです:
num = 15
変数 'num' をグローバルとして宣言し、それに値 15 を割り当てるだけです。これを厳密にチェックするフレームワークの一部として lua を使用していますか?
編集:このエラーを表面に出さずに「キャッチ」する簡単な方法は、このように pcall で割り当てをラップすることです...
pcall(function() num[2] = 15 end)
これを印刷すると、出力が得られます。
false test2.lua:18: attempt to index global 'num' (a nil value)
これにより、少なくとも何が起こったのかがわかります。関数に名前を付ければ、回復を試みることができると思います。
function TrySetValue()
num[2] = 15
end
local result, msg = pcall(TrySetValue)
if (not result) then
num = {}
end
result, msg = pcall(TrySetValue)
print(result, msg)
print(num[2])
おそらく前もってコードを修正するだけでよいのに、非常に多くの作業のように思えます。