如何在 __eq 元方法内访问指针?

我有几个 Lua 对象共享一个带有 __eq 元方法的元表。在此元方法内部,我想在比较之前检查这两个对象是否是同一个对象。就像在Java中你会做 a == b || a.compareTo(b) 那样。但问题在于,在 __eq 内使用 == 会调用 __eq,从而导致栈溢出。我该怎么做?

local t1 = { x = 3 }
local t2 = { x = 3 }
local t3 = t1
print(t1 == t3) -- 真,它们指向同一内存
local mt = {
    __eq = function(lhs, rhs)
        if lhs == rhs then return true end -- 导致栈溢出
        return lhs.x == rhs.x
    end
}
setmetatable(t1, mt)
setmetatable(t2, mt)

-- 下面有栈溢出
print(t1 == t2) -- 这应该比较 'x' 变量
print(t1 == t3) -- 这不需要这样做,相同的内存位置
点赞
用户5675002
用户5675002

请查看 rawequal() 函数。它将在不调用元方法的情况下比较实例。

2018-02-03 10:33:35
用户107090
用户107090

因为 Lua 仅在 userdata 指针不同时才会调用 __eq 的元方法,所以不需要在 __eq 元方法内进行相等性测试。

在设置元表后添加 print(t1 == t3) 来确认这一点。

手册 中说道(强调部分已加粗):

__eq: 等于(==)操作。与加法操作类似的行为, 不同之处在于当进行比较的值既不是两个表也不是两个原始的 userdata 时,Lua 才会尝试使用元方法

2018-02-03 10:53:55