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.