# Metatable compare problem

I want to achieve a complete vec2 (Vector2) class using Metatables.
However, there’s a somewhat confusing problem: “attempt to compare table”

Here’s the script that creates the class values:

``````local vec2 = require(script.Parent.vec2)
-- Print either true or false, but I'm getting errors instead.
print(tostring(vec2(5, 21) < vec2(7, 26)))
``````

I’m just keeping things simple for me right now, as this is the very first time I learned how to tie a knot with metatables. I’m just really excited, because somehow I just suddenly understood how to use metatables, after weeks of constant confused confusing confusion!

Here’s the error I’m getting while trying to do any compare methods (==, <=, <):

`attempt to compare table`

I haven’t found a single solution around the internet, this might be really stupid but I don’t understand why this won’t work.

And finally, here's the class module:
``````local function new(x, y)
return setmetatable(
{
__type = "vec2",
x = x or 0,
y = y or 0
},
{ -- Functions
__index = self,
__newindex = function(self, i, v)
return rawset(self, i, v)
end,
if (typeof(a) == "number") then
return new(a + b.x, a + b.y)
elseif (typeof(b) == "number") then
return new(a.x + b, a.y + b)
else
return new(a.x + b.x, a.y + b.y)
end
end,
__sub = function(a, b)
if (typeof(a) == "number") then
return new(a - b.x, a - b.y)
elseif (typeof(b) == "number") then
return new(a.x - b, a.y - b)
else
return new(a.x - b.x, a.y - b.y)
end
end,
__mul = function(a, b)
if (typeof(a) == "number") then
return new(a * b.x, a * b.y)
elseif (typeof(b) == "number") then
return new(a.x * b, a.y * b)
else
return new(a.x * b.x, a.y * b.y)
end
end,
__div = function(a, b)
if (typeof(a) == "number") then
return new(a / b.x, a / b.y)
elseif (typeof(b) == "number") then
return new(a.x / b, a.y / b)
else
return new(a.x / b.x, a.y / b.y)
end
end,
__mod = function(a, b)
if (typeof(a) == "number") then
return new(a % b.x, a % b.y)
elseif (typeof(b) == "number") then
return new(a.x % b, a.y % b)
else
return new(a.x % b.x, a.y % b.y)
end
end,
__pow = function(a, b)
if (typeof(a) == "number") then
return new(a ^ b.x, a ^ b.y)
elseif (typeof(b) == "number") then
return new(a.x ^ b, a.y ^ b)
else
return new(a.x ^ b.x, a.y ^ b.y)
end
end,
__eq = function(a, b)
if (typeof(a) == "number") then
return (a == b.x) and (a == b.y)
elseif (typeof(b) == "number") then
return (a.x == b) and (a.y == b)
else
return (a.x == b.x) and (a.y == b.y)
end
end,
__lt = function(a, b)
if (typeof(a) == "number") then
return (a < b.x) and (a < b.y)
elseif (typeof(b) == "number") then
return (a.x < b) and (a.y < b)
else
return (a.x < b.x) and (a.y < b.y)
end
end,
__le = function(a, b)
if (typeof(a) == "number") then
return (a <= b.x) and (a <= b.y)
elseif (typeof(b) == "number") then
return (a.x <= b) and (a.y <= b)
else
return (a.x <= b.x) and (a.y <= b.y)
end
end,
__tostring = function(a)
return a.x .. " " .. a.y
end,
__unm = function(a)
return new(-a.x, -a.y)
end
}
)
end

return new
``````

The arithmetic methods work just fine, the logical methods don’t.

Consider moving the metatable out of the function. Your current code creates a new metatable every time `new` is called.

``````local new
local mt = { -- Functions
__newindex = function(self, i, v)
return rawset(self, i, v)
end,
if (typeof(a) == "number") then
return new(a + b.x, a + b.y)
elseif (typeof(b) == "number") then
return new(a.x + b, a.y + b)
else
return new(a.x + b.x, a.y + b.y)
end
end,
__sub = function(a, b)
if (typeof(a) == "number") then
return new(a - b.x, a - b.y)
elseif (typeof(b) == "number") then
return new(a.x - b, a.y - b)
else
return new(a.x - b.x, a.y - b.y)
end
end,
__mul = function(a, b)
if (typeof(a) == "number") then
return new(a * b.x, a * b.y)
elseif (typeof(b) == "number") then
return new(a.x * b, a.y * b)
else
return new(a.x * b.x, a.y * b.y)
end
end,
__div = function(a, b)
if (typeof(a) == "number") then
return new(a / b.x, a / b.y)
elseif (typeof(b) == "number") then
return new(a.x / b, a.y / b)
else
return new(a.x / b.x, a.y / b.y)
end
end,
__mod = function(a, b)
if (typeof(a) == "number") then
return new(a % b.x, a % b.y)
elseif (typeof(b) == "number") then
return new(a.x % b, a.y % b)
else
return new(a.x % b.x, a.y % b.y)
end
end,
__pow = function(a, b)
if (typeof(a) == "number") then
return new(a ^ b.x, a ^ b.y)
elseif (typeof(b) == "number") then
return new(a.x ^ b, a.y ^ b)
else
return new(a.x ^ b.x, a.y ^ b.y)
end
end,
__eq = function(a, b)
if (typeof(a) == "number") then
return (a == b.x) and (a == b.y)
elseif (typeof(b) == "number") then
return (a.x == b) and (a.y == b)
else
return (a.x == b.x) and (a.y == b.y)
end
end,
__lt = function(a, b)
if (typeof(a) == "number") then
return (a < b.x) and (a < b.y)
elseif (typeof(b) == "number") then
return (a.x < b) and (a.y < b)
else
return (a.x < b.x) and (a.y < b.y)
end
end,
__le = function(a, b)
if (typeof(a) == "number") then
return (a <= b.x) and (a <= b.y)
elseif (typeof(b) == "number") then
return (a.x <= b) and (a.y <= b)
else
return (a.x <= b.x) and (a.y <= b.y)
end
end,
__tostring = function(a)
return a.x .. " " .. a.y
end,
__unm = function(a)
return new(-a.x, -a.y)
end
}
mt.__index = mt
function new(x, y)
return setmetatable(
{
__type = "vec2",
x = x or 0,
y = y or 0
},
mt
)
end

return new
``````

Your current code doesn’t need `__newindex`, so you could remove it (for now).

2 Likes