__eq does not seem to work

Note: I cannot post bug reports, and the issue might be at my end.

The __eq metamethod doesn’t seem to work. Neither of these 3 samples works:

local t = setmetatable({}, {
    __eq = function()
        return true
    end,
})

print(t == {}) -- should print true, but prints false
local t = {}
setmetatable(t, {
    __eq = function()
        return true
    end,
})

print(t == {}) -- should print true, but prints false
local t = {}
t.__eq = function()
    return true
end

print(t == {}) -- should print true, but prints false

Am I missing something?

  1. This isn’t true:
    Subtle behavior change in __eq
  2. Even it it were, that’s irrelevant. I want to override the equal operator :frowning:

I haven’t seen or realised this, if my explanation is not true then it is beyond me, thank you for the clarification

(also my bad kind of got the question twisted)

Upon further investigation, this seems to be a Roblox/Luau issue. Running any of the examples in the official Lua demo page returns true.

I’ll investigate if it’s Luau specific and file bug reports there.

Edit: it is indeed a Luau bug. Will bug report on GH.

Edit the second: __eq metamethod does not work · Issue #1051 · Roblox/luau · GitHub

If I understood the documentation (https://create.roblox.com/docs/luau/metatables) correctly, this is intended behavior in luau.
image

could it be he is missing the arguments?

Tested it out with this in mind and it does work just in fine. I do find this strangely obscure, and I’m not sure why it works on Lua.
Code:

function equal()
	return true
end
local meta = {
	__eq = equal
}
local t = setmetatable({}, meta)
local tw = setmetatable({}, meta)
print(t == tw)

@x1_EE OP’s code doesn’t work even with the arguments.

1 Like

You appear to be correct. This is weird.

Because it doesn’t make sense not to work. Why would a requirement for comparasion be that both objects should define __eq? What if I wanted to build a custom number class (e.g. Integer), and want to implement comparing with a regular number?

Edit: I should probably mention my original use case. I’m building something like FFlags for my game, which consists of a module with keys for the various flags.

export type FlagState = "Disabled" | "Development" | "Production"

local GFlags = {}

function GFlags.shouldRun(flag: FlagState | string)
	if flag == "Production" then
		return true
	elseif flag == "Development" then
		return RunService:IsStudio()
	else
		return false
	end
end

GFlags.NEW_FEATURE = "Disabled" :: FlagState

return GFlags

This lets me fine-grain features for the game. This works, but I wanted to make sure someone isn’t shooting theirselves in the foot like this:

if GFlags.NEW_FEATURE then
    -- always runs! not good
end

So the workaround was to create some kind of object, it’d work something like this

local function CREATEFLAG(state: FlagState): Flag
	return {
		State = state,
                __eq = function()
                    error("Use GFlags.shouldRun()")
                end
	}
end

function GFlags.shouldRun(flag: Flag)
	if flag.State == "Production" then
		return true
	elseif flag.State == "Development" then
		return RunService:IsStudio()
	else
		return false
	end
end

GFlags.NEW_FEATURE = CREATEFLAG "Production"

This way, if someone doesn’t use shouldRun, Luau would run a comparasion check GFlags.NEW_FEATURE == true, which would in turn call the __eq, and error. This is possible in Lua, but not in Luau.

Note As it turns out, both Luau and Lua optimize comparasion operators with constants (so GFlags.NEW_FEATURE == true will be optimized to true == GFlags.NEW_FEATURE), so this wouldn’t have worked. But the behavior is still weird.

Perhaps the reason is that if the objects being compared have different __eq metamethods, the __eq of the one on the left side of the comparison could give a different result than the __eq of the one on the right side of the equation.

Although order usually doesn’t matter in equality comparisons, If you compare two objects with different __eq metamethods in Lua, you may get different results depending on which one is on the left side and which one is on the right side of the equation. Apparently Lua decides the equality based on the __eq metamethod of the object on the left side of the equation if both of them have an __eq metamethod. I tested this in a lua app.

However, I do agree that being able to compare different types of objects could be useful.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.