Back to Blog

Lua with Neovim: Metatables — __tostring, __add, __eq, __index & Custom Table Behavior | Episode 29

Sandy LaneSandy Lane

Video: Lua with Neovim: Metatables — __tostring, __add, __eq, __index & Custom Table Behavior | Episode 29 by Taught by Celeste AI - AI Coding Coach

Watch full page →

Lua with Neovim: Metatables — __tostring, __add, __eq, __index & Custom Table Behavior

Metatables in Lua allow you to customize how tables behave by defining special metamethods. This tutorial covers attaching metatables to tables using setmetatable, customizing string output with __tostring, overloading operators like addition and equality with __add and __eq, and using __index as a fallback for missing keys—laying the groundwork for object-oriented programming in Lua.

Code

-- Define a Vector "class" with x and y coordinates
local Vector = {}
Vector.__index = Vector  -- Set __index to itself for method lookup

-- Constructor for Vector
function Vector.new(x, y)
  local self = setmetatable({}, Vector)
  self.x = x
  self.y = y
  return self
end

-- __tostring metamethod to customize print output
function Vector:__tostring()
  return "(" .. self.x .. ", " .. self.y .. ")"
end

-- __add metamethod to add two vectors
function Vector:__add(other)
  return Vector.new(self.x + other.x, self.y + other.y)
end

-- __eq metamethod to compare two vectors for equality
function Vector:__eq(other)
  return self.x == other.x and self.y == other.y
end

-- Set the metatable for Vector to itself to enable metamethods
setmetatable(Vector, {
  __call = function(_, x, y)
    return Vector.new(x, y)
  end
})

-- Usage examples
local v1 = Vector(3, 4)
local v2 = Vector(1, 2)
print(v1)                 -- Output: (3, 4)
print(v2)                 -- Output: (1, 2)
local v3 = v1 + v2        -- Uses __add
print(v3)                 -- Output: (4, 6)
print(v1 == v2)           -- Uses __eq, output: false
print(v1 == Vector(3, 4)) -- Output: true

-- __index fallback example:
local fallback = {default = "N/A"}
local t = setmetatable({a = 1}, {__index = fallback})
print(t.a)        -- Output: 1 (found in table)
print(t.default)  -- Output: N/A (fallback via __index)
print(t.missing)  -- Output: N/A (fallback via __index)

Key Points

  • setmetatable(t, mt) attaches a metatable mt that customizes table t behavior.
  • __tostring defines how a table converts to a string, affecting print() output.
  • __add and __eq metamethods enable operator overloading for addition and equality checks.
  • __index provides a fallback lookup when a key is not found in the table, supporting inheritance and defaults.
  • Metatables form the foundation for object-oriented programming and inheritance patterns in Lua.