Lua - Customizing Comparisons



By default Lua tables are compared by reference which means two tables are same if they are same object in memory. We can overload comparison operators like ==, < and so easily. Following are the fields of a metatable, we can use to customize comparisons of table −

  • __eq to overload equality (==) operator.

  • __lt to overload less than (<) operator.

  • __le to overload less than or equal to (<=) operator.

These metamethods allows to define the behavior of the table used with comparision operators. This is especially useful, when we need to deal with custom domain based types like point, vertex etc.

Example - Behavior of == Operator

In case, we're not having __eq metamethod for any of the table, Lua will compare tables using reference as shown in example below −

main.lua

-- table 1
local table1 = { a = 1}
-- table 2
local table2 = { a = 1}

-- prints true being same object
print(table1 == table1)  

-- prints false as different object
print(table1 == table2)  

Output

When we run the above program, we will get the following output−

true
false

Example - Overloading == Operator

In below example, we've a more relevant example where two points are to be compared. In order to compare two points using == operator or < operator, we've implemented __eq and __lt metamethods as shown below −

main.lua

-- create a metatable for Point
local Point = {
   -- overload == operator
   __eq = function(p1, p2)
      return (p1.x == p2.x and p1.y == p2.y)
   end

   -- overload < operator   
   __lt = function(p1, p2)
      return (p1.x^2 + p1.y^2) < (p2.x^2 + p2.y^2)
   end
}

-- method to create a point instance
function Point.new(x, y)
  return setmetatable({ x = x, y = y }, Point)
end

-- create point instances
local p1 = Point.new(1, 2)
local p2 = Point.new(1, 2)
local p3 = Point.new(3, 4)

-- prints true as both are same points as per our custom equality logic
print(p1 == p2) -- Output: true
-- print false being different
print(p1 == p3) -- Output: false

-- prints true, as p1 is nearer to 0,0.
print(p1 < p3)  
-- prints false
print(p3 < p1)  

Output

When we run the above program, we will get the following output−

true
false
true
false
Advertisements