2013-05-11 19 views
6

例にこれらの間__indexメタメソッドの振る舞いに差がある理由は、私が悩みの理解を持っている:Luaのメタテーブル矛盾

なくなり lua: l.lua:8: attempt to call method 'speak' (a nil value)

A = { __index = A } 
function A:speak() 
    print("I'm an A") 
end 
An_A = setmetatable({},A) 
An_A:speak() 

は、次のようなエラーが発生します

B = { __index = function(t,key) return B[key] end } 
function B:speak() 
    print("I'm an B") 
end 
An_B = setmetatable({},B) 
An_B:speak() 

期待どおりに実行され、I'm an Bを出力します。これは私がPILのthisセクションを読んでそうであった理由を理解しようとして


。このの私の理解では、「A」を含むスニペットでは、(上記の引用のboldened segmenetあたりとして)アクセスは、テーブルAで行うことになり__index = Aことです

The use of the __index metamethod for inheritance is so common that Lua provides a shortcut. Despite the name, the __index metamethod does not need to be a function: It can be a table, instead. When it is a function, Lua calls it with the table and the absent key as its arguments. When it is a table, Lua redoes the access in that table.

:それはと述べています。これが当てはまる場合、なぜキー"speak"に関連する機能が見つからないのかわかりません。これを修正しようとする試みで、keyに関連付けられた値を返すBスニペットに関数アプローチを実装することにしました。それはBになりました。確かに__index = Aおよび(Bに適合)__index = function(t,key) return A[key] endは同じ効果を有する。

いずれかの明確化は非常に認められる。

答えて

9

最初の例で起こっていることは、A.__index == nilです。あなたがここにあなたの最初の行に「A」を作成した場合:

A = { __index = A } 

割り当て、それはこの時点ではまだ存在しないため、「」nilに評価の右側。その結果、後であなたがここにメタテーブルを設定する場合:

An_A = setmetatable({},A) 

それは本当にこれに似た何かをやって終わる:

An_A = setmetatable({}, {__index = nil}) 

が、それはあなたが望むように動作させるためには、あなたがする必要があります__indexnilでないことを確認してください。例えば、テーブルの構築後にそれを割り当てます。

A = {} 
A.__index = A 

function A:speak() 
    print("I'm an A") 
end 
An_A = setmetatable({},A) 
An_A:speak()    --> outputs I'm an A 
+0

は偉大な説明をありがとう、起こるだろう、私はそのような= F 'として何か他の言語のようになると想定していた私には発生しませんでしたλn:f(n) 'が有効である。歓声: – HennyH

+1

@HennyH: 'f = function(n)return f(n)end'は同じ理由からluaでは問題ありません。同等の失敗したPythonは 'd = {" __index ":d}'ですが、Pythonは 'NameError'を返します。 – Eric

+0

@Eric再帰関数は同じパターンに従うとします。 – HennyH