[解決済み] Lua 5.1の__callメタメソッドは、実際にはどのように動作するのでしょうか?
質問
練習として、Luaでセットの実装を作ろうとしています。 具体的には、Pil2 11.5の単純化されたセット実装を、値の挿入、値の削除などの機能を含むように成長させたいと考えています。
さて、これを行うための明白な方法(そして実際に機能する方法)はこうです。
Set = {}
function Set.new(l)
local s = {}
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.insert(s, v)
s[v] = true
end
ts = Set.new {1,2,3,4,5}
Set.insert(ts, 5)
Set.insert(ts, 6)
for k in pairs(ts) do
print(k)
end
予想通り、1から6までの数字がプリントアウトされました。 しかし、これらの
Set.insert(s, value)
は本当に醜いです。 むしろ、次のようなものを呼び出せるようにしたいものです。
ts:insert(value)
.
これを解決するために私が最初に試みたのは、次のようなものでした。
Set = {}
function Set.new(l)
local s = {
insert = function(t, v)
t[v] = true
end
}
for _, v in ipairs(l) do
s[v] = true
end
return s
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
これは、何が出てくるか見るまでは、ほとんど問題なく動作します。
1
2
3
4
5
6
insert
非常に明らかに、セットテーブルのメンバーであるinsert関数が表示されています。 これは、元の
Set.insert(s, v)
という問題が発生しやすくなります(例えば、誰かが入力しようとしている有効なキーが "insert" だった場合、どうなるでしょうか)。 もう一度、本を読んでみましょう。 代わりにこれを試すとどうなるのでしょうか?
Set = {}
function Set.new(l)
local s = {}
setmetatable(s, {__call = Set.call})
for _, v in ipairs(l) do
s[v] = true
end
return s
end
function Set.call(f)
return Set[f]
end
function Set.insert(t, v)
t[v] = true
end
ts = Set.new {1,2,3,4,5}
ts:insert(5)
ts:insert(6)
for k in pairs(ts) do
print(k)
end
今、私がこのコードを読んでいる方法は
-
を呼び出すと
ts:insert(5)
というのはinsert
が呼び出されるために存在しないことを意味します。ts
metatable が検索されることになります。"__call"
. -
は
ts
メタフェースの"__call"
キーが返すSet.call
. -
現在
Set.call
という名前で呼び出されます。insert
を返すようになります。Set.insert
関数を使用します。 -
Set.insert(ts, 5)
が呼び出されます。
実際に起きていることはこうだ。
lua: xasm.lua:26: attempt to call method 'insert' (a nil value)
stack traceback:
xasm.lua:26: in main chunk
[C]: ?
そして、この時点で私は行き詰ってしまったのです。 これからどうすればいいのか全く分からないのです。 このコードに様々な程度の絶望的なバリエーションを加えて1時間ハックし続けましたが、最終的には何も動作しないのです。 私はこの時点でどのような間違いなく明白なことを見落としているのでしょうか?
解決するには?
<ブロッククオート今、私がこのコードを読む方法は。
- ts:insert(5)を呼び出すと、呼び出されるinsertが存在しないということは、ts metatableが"__call"で検索されることになりますね。
そこにあなたの問題がある。 その
__call
メタメソッドが参照されるのは
テーブル自体
が呼び出されます(つまり、関数として)。
local ts = {}
local mt = {}
function mt.__call(...)
print("Table called!", ...)
end
setmetatable(ts, mt)
ts() --> prints "Table called!"
ts(5) --> prints "Table called!" and 5
ts"String construct-call" --> prints "Table called!" and "String construct-call"
Luaのオブジェクト指向のコロンコールはこんな感じです。
ts:insert(5)
の単なる構文上の糖分です。
ts.insert(ts,5)
の構文糖である。
ts["insert"](ts,5)
そのため、このアクションは
ts
は
コール
でなく
インデックス
(その
結果
の
ts["insert"]
と呼ばれるもの)に支配されている。
__index
メタメソッドです。
は
__index
メタメソッドには、インデックスを別のテーブルにフォールバックさせたい場合のテーブルを指定することができます (ただし、これは
の値は、__indexキー
は、インデックスを作成するメタテーブルと
ない
を使用します(メタ情報自体)。
local fallback = {example = 5}
local mt = {__index = fallback}
local ts = setmetatable({}, mt)
print(ts.example) --> prints 5
は
__index
メタメソッドを関数として使用する場合は、 Set.call で指定したシグネチャと同じように動作しますが、 キーの前にインデックスを作成するテーブルが渡されます。
local ff = {}
local mt = {}
function ff.example(...)
print("Example called!",...)
end
function mt.__index(s,k)
print("Indexing table named:", s.name)
return ff[k]
end
local ts = {name = "Bob"}
setmetatable(ts, mt)
ts.example(5) --> prints "Indexing table named:" and "Bob",
--> then on the next line "Example called!" and 5
メタテーブルの詳細については マニュアル .
関連
-
[解決済み] LUA がグローバルな nil 値のインデックスを作成しようとした
-
[解決済み] Luaにおける演算子~=の意味とは?
-
[解決済み] Luaのpairs()とipairs()の違いは何ですか?
-
[解決済み] "Unable to cast value to Object" エラーメッセージ
-
[解決済み] "ローカルへのインデックス作成試行..." なぜこのエラーが発生するのでしょうか?
-
[解決済み] WoW Lua - 1.13でスペルランクを取得する方法 (クラシック)
-
[解決済み] Lua が nil を呼び出そうとした
-
[解決済み] Luaでネストしたテーブルと数値キー
-
lua 5.2 で発生する可能性のあるいくつかのエラー
-
[解決済み] Luaでテーブルが要素を含んでいるかどうかを確認するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Luaテーブルのすべての要素を削除する方法は?
-
[解決済み] Luaにおける演算子~=の意味とは?
-
[解決済み] Luaスクリプトのメモリ使用量を制限する?
-
[解決済み] attempt to index upvalue」の意味を教えてください。
-
[解決済み] 何をするのか? for i=1,select('#',...)
-
[解決済み] トーチ[cpuType]の文法説明
-
lua 5.2 で発生する可能性のあるいくつかのエラー
-
lua が表示される xxx: nil 値 (フィールド 'getn') を呼び出そうとする 解決方法
-
luaのエラーまとめ
-
luaの一般的なエラーの種類