Lua global __newindex只调用一次

时间:2015-03-29 16:59:00

标签: lua lua-table

在7周内完成7种语言的Lua练习并遇到问题。

挑战是重载+运算符以便能够连接表(就像它们是数组一样)。

{ 1, 2, 3 } + { 4, 5, 6 } -- { 1, 2, 3, 4, 5, 6 }

所以我尝试使用__add metamethod并创建了一个metatable来托管它。

local mt = {
  __add = function(lhs, rhs)
    return concatenate(lhs, rhs)
  done
}

我错误地尝试在全局表上设置此metatable,但这显然不会传播到所有其他表。

为了尝试将其添加到所有创建的表中,我在_G上创建了一个单独的元表,它将使用__newindex元方法,然后设置每个__newindex激活的原始元表。

setmetatable(_G, {
  __newindex = function(array, index)
    setmetatable(array, mt)
  end
})

但是,这没有用:

a1 = { 1, 2, 3 }
a2 = { 4, 5, 6 }
a1 + a2

导致以下错误:attempt to perform arithmetic on global 'a1' (a nil value)

所以我把一个print语句放到全局metatable中,看它是否实际被调用:

setmetatable(_G, {
  __newindex = function(array, index)
    print('new table ' .. index)
    setmetatable(array, mt)
  end
})

这只会打印出要创建的第一个表:

a1 = { 1, 2, 3 }
a2 = { 4, 5, 6 }
a3 = { 4, 5, 6 }
a4 = { 4, 5, 6 }

结果:

new table a1

我希望我不小心覆盖某些内容,因为当我删除对setmetatable

的调用时
setmetatable(_G, {
  __newindex = function(array, index)
    print('new table ' .. index)
    --setmetatable(array, mt)
  end
})

按预期打印所有条目。

1 个答案:

答案 0 :(得分:3)

setmetatable(_G, {
    __newindex = function(array, index)
        print('new table ' .. index)
        setmetatable(array, mt)
    end
})

当您执行a1 = { 1, 2, 3 }时,__newindexarray,而_Gindexsetmetatable(array, mt)为' a1' 。然后调用_G将更改setmetatable的元表,撤消原始setmetatable(_G, { __newindex = function(array, index) setmetatable(array[index], mt) end }) 调用的效果。

你可能想要更像的东西:

__newindex

但是还有另一个问题,因为现在不再发生作业的原始效果。而是调用a1,因此array[index] = value仍为零值。

您可以在__newindex功能中尝试__newindex,但这会再次调用相同的rawset。相反,请使用setmetatable(_G, { __newindex = function(array, index, value) rawset(array, index, value) setmetatable(array[index], mt) end })

__newindex

请注意b = 1需要3个参数。

现在,当您将非表格分配给像{{1}}这样的全局<?p>时会发生什么