2.4中"Lua does not perform the primitive assignment."的含义(关于__newindex)
Meaning of "Lua does not perform the primitive assignment." in 2.4 (concerning __newindex)
来自 https://www.lua.org/manual/5.3/manual.html
见第 2.4 节。关于元方法操作 __newindex 陈述了以下引用:
__newindex: The indexing assignment table[key] = value. Like the index event, this event happens when table is not a table or when key is not
present in table. The metamethod is looked up in table.
Like with indexing, the metamethod for this event can be either a
function or a table. If it is a function, it is called with table,
key, and value as arguments. If it is a table, Lua does an indexing
assignment to this table with the same key and value. (This assignment
is regular, not raw, and therefore can trigger another metamethod.)
Whenever there is a __newindex metamethod, Lua does not perform the
primitive assignment. (If necessary, the metamethod itself can call
rawset to do the assignment.)
其中我问下面具体想说的是什么
"Lua does not perform the
primitive assignment. (If necessary, the metamethod itself can call
rawset to do the assignment.)"
这是否意味着如果值是一个数字,它是一个原始值,它不会通过元方法事件分配给提供的 table 而我们必须使用 rawget 或其他东西?这让我非常困惑和矛盾。
我想展示相同的示例来帮助您弄清这种困惑。
原始赋值示例:
local test = {}
test['x'] = 1 -- equal to rawset(test, 'x', 1)
print(test['x']) -- 1
print(rawget(test,'x')) -- 1
当 table test
没有 __newindex
元方法时,原始分配代码 test['x'] = 1
等于 rawset(test, 'x', 1)
。
然后 __newindex
元方法示例:
local test = {}
setmetatable(test, {__newindex = function(t,key,value) end})
test['x'] = 1
print(test['x']) -- nil
print(rawget(test,'x')) -- nil
赋值test['x'] = 1
将触发调用__newindex
函数。
如果 __newindex
什么都不做,那么什么也不会发生,我们将得到 test['x']
.
的零结果
如果__newindex
函数调用rawset
:
local test = {}
setmetatable(test, {
__newindex = function(t,key,value)
rawset(t,key,value) -- t:test key:'x' value:1
end})
test['x'] = 1
print(test['x']) -- 1
print(rawget(test,'x')) -- 1
代码与第一个例子效果相同。
所以手册说:
"Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.)"
那么问题来了,我们如何使用__newindex
呢?
table.
中可以用来分隔新旧索引
local test = {y = 1}
local newtest = {}
setmetatable(test, {
__newindex =
function(t,key,value)
newtest[key] = value
end,
__index = newtest
})
test["x"] = 1
print(test['x']) -- 1
print(test['y']) -- 1
print(rawget(test, 'x')) -- nil
print(rawget(test, 'y')) -- 1
旧索引'x'和新索引'y'都可以test[key]
访问,可以rawget(test, key)
分隔
来自 https://www.lua.org/manual/5.3/manual.html 见第 2.4 节。关于元方法操作 __newindex 陈述了以下引用:
__newindex: The indexing assignment table[key] = value. Like the index event, this event happens when table is not a table or when key is not present in table. The metamethod is looked up in table.
Like with indexing, the metamethod for this event can be either a function or a table. If it is a function, it is called with table, key, and value as arguments. If it is a table, Lua does an indexing assignment to this table with the same key and value. (This assignment is regular, not raw, and therefore can trigger another metamethod.)
Whenever there is a __newindex metamethod, Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.)
其中我问下面具体想说的是什么
"Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.)"
这是否意味着如果值是一个数字,它是一个原始值,它不会通过元方法事件分配给提供的 table 而我们必须使用 rawget 或其他东西?这让我非常困惑和矛盾。
我想展示相同的示例来帮助您弄清这种困惑。 原始赋值示例:
local test = {}
test['x'] = 1 -- equal to rawset(test, 'x', 1)
print(test['x']) -- 1
print(rawget(test,'x')) -- 1
当 table test
没有 __newindex
元方法时,原始分配代码 test['x'] = 1
等于 rawset(test, 'x', 1)
。
然后 __newindex
元方法示例:
local test = {}
setmetatable(test, {__newindex = function(t,key,value) end})
test['x'] = 1
print(test['x']) -- nil
print(rawget(test,'x')) -- nil
赋值test['x'] = 1
将触发调用__newindex
函数。
如果 __newindex
什么都不做,那么什么也不会发生,我们将得到 test['x']
.
如果__newindex
函数调用rawset
:
local test = {}
setmetatable(test, {
__newindex = function(t,key,value)
rawset(t,key,value) -- t:test key:'x' value:1
end})
test['x'] = 1
print(test['x']) -- 1
print(rawget(test,'x')) -- 1
代码与第一个例子效果相同。 所以手册说:
"Lua does not perform the primitive assignment. (If necessary, the metamethod itself can call rawset to do the assignment.)"
那么问题来了,我们如何使用__newindex
呢?
table.
local test = {y = 1}
local newtest = {}
setmetatable(test, {
__newindex =
function(t,key,value)
newtest[key] = value
end,
__index = newtest
})
test["x"] = 1
print(test['x']) -- 1
print(test['y']) -- 1
print(rawget(test, 'x')) -- nil
print(rawget(test, 'y')) -- 1
旧索引'x'和新索引'y'都可以test[key]
访问,可以rawget(test, key)