Why is this metamethod returning a bool?

Goal: Setup equality of tables not by returning a single true/false statement but instead, a vector of them for each respective comparison.
E.g. {1, 2, 3, 4} == {1, 2, 3, 3} should give { true, true, true, false }

Problem below: The output table, newArr is the expected and correct solution. However, when printing it’s type outside the function (after it is returned as output), it goes from type table to boolean. Why?

Code snippet to try and fix yourself:

local Vector = {__type = "vector"};

function Vector.__eq(array, value)
    local newArr = setmetatable({}, Vector)

    for i, v in ipairs(value) do
        newArr[i] = array[i] == v
        print(i, newArr[i])
    end
    print(type(newArr))
    return newArr
end

local v = setmetatable({1, 2, 3, 4}, Vector)
local v2 = setmetatable({1, 2, 3, 3}, Vector)
local result = type(v == v2)
print(result)

With the relational metamethods, if you return a truthy value, it returns true. So you can’t get a non-bool from a relational operation. Why did you need to get a table from == though? lol

1 Like

I’m trying to create a which() function which can do for example,

local array1 = setmetatable({1, 0, 2, 2}, Vector)
local array2 = setmetatable({2, 0, 2, 4}, Vector)
which(array2 == array1) 
-> First, array1 == array2 would ideally give {false, true, true, false} 
-> which() then returns a table of the indexes with true values -> {2, 3}

The use case is to have any arbitrary conditional statement within my which function such as,
which(2*array > sqrt(array2)). [I have other metamethods that allow for multiplication of arrays and function composition where both return a new table.]

it might make more sense to just check if the arrays are equal and return a boolean that tells whether they’re equal instead of whether each specific value is equal to its counterpart.

function Vector.__eq(array, value)
	for i, v in pairs(array) do
		if (v ~= value[i]) then
			return false
		end
	end
	
	return true
end

For this case i would probably make a custom equal function that you can use as an alternative to == if you really want a non-boolean result, since the point of overloading relational operators is so they can return true if custom types have the same data even though they are different instances, or one data is greater than the other, etc.

local function equal(a, b)
    return Vector.__eq(a, b)
end

I am assuming you already have the implementation ready, but the only hurdle being you can’t use == to get your desired result

1 Like