Menu
Coddy logo textTech

Arithmetic Metamethods Part 2

Part of the Logic & Flow section of Coddy's Lua journey — lesson 22 of 54.

Building on addition and subtraction, you can also define multiplication and division behavior for your tables using the __mul and __div metamethods. These work the same way as __add and __sub, but they respond to the * and / operators.

The __mul metamethod is particularly useful when you want to scale a table's values. For example, multiplying a vector by a number (called a scalar) should multiply each component:

local vector = {x = 3, y = 4}

local meta = {
    __mul = function(a, b)
        local scalar = type(a) == "number" and a or b
        local vec = type(a) == "table" and a or b
        return {x = vec.x * scalar, y = vec.y * scalar}
    end
}

setmetatable(vector, meta)

local scaled = vector * 2
print(scaled.x, scaled.y)  -- Output: 6  8

Notice how the function checks which operand is the number and which is the table. This allows both vector * 2 and 2 * vector to work correctly.

The __div metamethod works similarly for division:

local meta = {
    __div = function(a, b)
        return {x = a.x / b, y = a.y / b}
    end
}

setmetatable(vector, meta)

local divided = vector / 2
print(divided.x, divided.y)  -- Output: 1.5  2

These metamethods complete the basic arithmetic operations for your custom types, giving you full control over how mathematical operators behave with your tables.

challenge icon

Challenge

Easy

Write a function scaleVector that takes x, y, and scalar and returns the scaled vector as a formatted string.

Create a vector table with the given coordinates, attach a metatable with the __mul metamethod to enable scalar multiplication, multiply the vector by the scalar using the * operator, and return the result.

Logic:

  • Create a vector table with keys x and y set to the provided coordinates
  • Create a metatable with __mul that handles multiplication between a vector and a scalar
  • The __mul function should check which operand is the number and which is the table
  • Return a new table with x = vec.x * scalar and y = vec.y * scalar
  • Attach the metatable to the vector table using setmetatable()
  • Multiply the vector by the scalar using vector * scalar
  • Return the result as a string in the format "x y" (the x and y values separated by a space)

Parameters:

  • x (number): The x-coordinate of the vector
  • y (number): The y-coordinate of the vector
  • scalar (number): The scalar value to multiply the vector by

Returns: The scaled vector as a string in the format "x y" (string)

Cheat sheet

The __mul and __div metamethods define multiplication and division behavior for tables, responding to the * and / operators.

The __mul metamethod is useful for scaling table values. When multiplying a vector by a scalar, check which operand is the number and which is the table to allow both vector * 2 and 2 * vector:

local vector = {x = 3, y = 4}

local meta = {
    __mul = function(a, b)
        local scalar = type(a) == "number" and a or b
        local vec = type(a) == "table" and a or b
        return {x = vec.x * scalar, y = vec.y * scalar}
    end
}

setmetatable(vector, meta)

local scaled = vector * 2
print(scaled.x, scaled.y)  -- Output: 6  8

The __div metamethod works similarly for division:

local meta = {
    __div = function(a, b)
        return {x = a.x / b, y = a.y / b}
    end
}

setmetatable(vector, meta)

local divided = vector / 2
print(divided.x, divided.y)  -- Output: 1.5  2

Try it yourself

function scaleVector(x, y, scalar)
    -- Write code here
end
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Logic & Flow