【问题标题】:Lua __eq on tables with different metatablesLua __eq 在具有不同元表的表上
【发布时间】:2020-09-08 18:32:57
【问题描述】:

我在这个网站http://lua-users.org/wiki/MetamethodsTutorial找到了以下引用:

当在两个表上使用 == 运算符时调用 __eq,引用相等性检查失败,并且两个表具有相同的 __eq 元方法 (!)。

现在我用 Lua 5.3.5 对其进行了测试,这根本不是我观察到的:

a = {}
b = {}
m = {}
m2 = {}
setmetatable(a, m)
setmetatable(b, m2)
m.__eq = function(p1, p2) print("why"); return true end
m2.__eq = function(p1, p2) print("why2"); return true end

这是我测试的代码。

> a == b
why
true
> b == a
why2
true

看起来它和比较运算符做的事情一样,它只是获取左表并使用它的元方法。

最近的 Lua 版本是否发生了这种变化,还是我的测试出错了?

感谢您的帮助。

【问题讨论】:

    标签: lua equality meta-method


    【解决方案1】:

    这在 Lua 5.3 中发生了变化。 The readme 表示它为“一些元方法引入了更灵活的规则”。比较the Lua 5.2 reference manual

    == 操作。函数getequalhandler 定义了 Lua 如何为相等性选择元方法。只有当被比较的两个值具有相同的类型和所选操作的相同元方法,并且值是表或完整的用户数据时,才会选择元方法。

         function getequalhandler (op1, op2)
           if type(op1) ~= type(op2) or
              (type(op1) ~= "table" and type(op1) ~= "userdata") then
             return nil     -- different values
           end
           local mm1 = metatable(op1).__eq
           local mm2 = metatable(op2).__eq
           if mm1 == mm2 then return mm1 else return nil end
         end
    

    “eq”事件定义如下:

         function eq_event (op1, op2)
           if op1 == op2 then   -- primitive equal?
             return true   -- values are equal
           end
           -- try metamethod
           local h = getequalhandler(op1, op2)
           if h then
             return not not h(op1, op2)
           else
             return false
           end
         end
    

    请注意,结果始终是布尔值。

    the Lua 5.3 reference manual:

    相等 (==) 操作。行为类似于加法操作,除了 Lua 仅当被比较的值是两个表或两个完整的用户数据并且它们在原始上不相等时才会尝试元方法。调用的结果总是被转换为布尔值。

    【讨论】:

    • 这是我怀疑的,但我在参考文献中找不到正确的段落。这是我没想到的行为上的巨大变化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 2016-03-07
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多