api - “Lua 不执行原始分配”的含义。在 2.4 中(关于 __newindex)
问题描述
来自https://www.lua.org/manual/5.3/manual.html 见第 2.4 节。关于元方法操作 __newindex 声明以下引用:
__newindex:索引分配表[key] = value。与索引事件一样,当表不是表或表中不存在键时,会发生此事件。元方法在表中查找。
与索引一样,此事件的元方法可以是函数或表。如果它是一个函数,则使用表、键和值作为参数调用它。如果它是一个表,Lua 会使用相同的键和值对该表进行索引分配。(这个赋值是常规的,不是原始的,因此可以触发另一个元方法。)
只要有 __newindex 元方法,Lua 就不会执行原语赋值。(如有必要,元方法本身可以调用 rawset 进行赋值。)
其中我问下面的具体打算说什么
“Lua 不执行原始赋值。(如果需要,元方法本身可以调用 rawset 来进行赋值。)”
这是否意味着如果该值是一个数字,这是一个原语,它不会通过元方法事件分配给提供的表,我们必须使用 rawget 什么的?这对我来说非常混乱和矛盾。
解决方案
我想展示同样的例子来帮助你弄清楚这种困惑。原始赋值示例:
local test = {}
test['x'] = 1 -- equal to rawset(test, 'x', 1)
print(test['x']) -- 1
print(rawget(test,'x')) -- 1
原始分配代码test['x'] = 1
等于rawset(test, 'x', 1)
表test
没有__newindex
元方法时。
然后是__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
什么都不做,那么什么也不会发生,我们将得到 nil 结果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 不执行原始赋值。(如果需要,元方法本身可以调用 rawset 来进行赋值。)”
那么问题来了,我们该如何使用__newindex
呢?它可以用来分隔表中的新旧索引。
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)
推荐阅读
- amazon-web-services - 是否可以在 AWS IAM 的显式拒绝中添加异常?
- vue.js - Vue.JS 在部署时获取内容处置标头的问题
- python - 在 Django 中从外部 API 获取数据
- python - Pandas 根据当前 df 中的列创建一个新的 df
- javascript - 使管道以角度自我刷新
- python - 来自 Python 的 Google 大查询
- testing - 如何检查赛普拉斯是否在测试运行器(赛普拉斯打开)与赛普拉斯运行中运行?
- git - 如何最好地进行 bitbucket 管道自动版本控制?
- reactjs - 反应切换功能
- javascript - 当接收到的数据是数组时,无法从 json-server 读取 url 参数