Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Why won't some metamethods work properly?

Asked by 2 years ago
Edited 2 years ago

I'm using metamethods for my "Number Instance" module to act like real numbers. Most of the metamethods are working fine, except for these three: __eq, __le, and __lt. They are scripted the same way with __concat, __add, __sub, __mul, __div, __mod, and __pow, but they won't work properly as expected. I tried printing them in a script and this is what they printed:

01local NumberService = require(game:GetService("ReplicatedStorage"):WaitForChild("CustomServices")):GetService("NumberService")
02 
03local TestNumber = NumberService.new(50)
04 
05print("My number is " .. TestNumber) -- "My number is 50" (working) __concat
06print(-TestNumber) -- -50 (working) __unm
07print(TestNumber + 50) -- 100 (working) __add
08print(60 - TestNumber) -- 10 (working) __sub
09print(TestNumber * 2) -- 100 (working) __mul
10print(50 / TestNumber) -- 1 (working) __div
11print(TestNumber % 28) -- 22 (working) __mod
12print(2 ^ TestNumber) -- 1125899906842624 (working) __pow
13print(tostring(TestNumber)) -- "50" (working) __tostring
14print(50 == TestNumber) -- false (not working) __eq
15print(TestNumber < 60) -- attempt to compare table < number (not working) __lt
16print(TestNumber > 60) -- attempt to compare table > number (not working) __lt
17print(40 <= TestNumber) -- attempt to compare table <= number (not working) __le
18print(TestNumber >= 40) -- attempt to compare table >= number (not working) __lt
19print(#TestNumber) -- attempt to get length of a number value (working) __len

This is the expected output to the lines that are not working

1print(50 == TestNumber) -- true
2print(TestNumber < 60) -- true
3print(TestNumber > 60) -- false
4print(40 <= TestNumber) -- true
5print(TestNumber >= 50) -- true

And this is the module script

001newNumber.__index = NumberInstance
002newNumber.__concat = function(a, b)
003    local isNumberInstance1 = typeof(a):lower() == "table" and a.Number ~= nil
004    local isNumberInstance2 = typeof(b):lower() == "table" and b.Number ~= nil
005 
006    if isNumberInstance1 and isNumberInstance2 then
007        return a.Number .. b.Number
008    elseif isNumberInstance1 and not isNumberInstance2 then
009        return a.Number .. b
010    elseif not isNumberInstance1 and isNumberInstance2 then
011        return a .. b.Number
012    elseif not isNumberInstance1 and not isNumberInstance2 then
013        return a .. b
014    end
015end
View all 150 lines...

1 answer

Log in to vote
1
Answered by
Xapelize 2658 Moderation Voter Community Moderator
2 years ago

It turns out __eq, _lt, and __le doesn't fire if the other token is a different datatype from the class.

For example:

MyCustomClass == "30"

Let's say you have a backend code that helps you to return the value MyCustomClass.String == "30", it will still not fire because MyCustomClass does not share the same datatype with "30". This rule is shared with the equal, bigger, or less than the comparative operator.

Also, a workaround is to do NumberService.new(50) == TestNumber in your case, so 50 shares the same datatype with TestNumber.

Ad

Answer this question