Доступ к указателям внутри мета-метода __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) -- true, they pointer to same memory
local mt = {
    __eq = function(lhs, rhs)
        if lhs == rhs then return true end -- causes stack overflow
        return lhs.x == rhs.x
    end
}
setmetatable(t1, mt)
setmetatable(t2, mt)

-- stack overflow below
print(t1 == t2) -- this should compare 'x' variables
print(t1 == t3) -- this shouldn't need to do so, same memory location

2 ответа

Решение

Нет необходимости проверять равенство внутри __eq метаметод, потому что Луа называет только __eq метаметод, если указатели пользовательских данных отличаются.

добавлять print(t1 == t3) сразу после установки метатаблицы, чтобы подтвердить это.

В руководстве сказано (выделено):

__eq: равная (==) операция. Поведение аналогично операции сложения, за исключением того, что Lua будет пытаться использовать метаметод только тогда, когда сравниваемые значения являются либо обеими таблицами, либо обоими полными пользовательскими данными, и они не равны примитивно.

Проверьте rawequal() функция. Он будет сравнивать экземпляры без вызова метаметодов.

Другие вопросы по тегам