Доступ к указателям внутри мета-метода __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()
функция. Он будет сравнивать экземпляры без вызова метаметодов.