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 8Notice 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 2These metamethods complete the basic arithmetic operations for your custom types, giving you full control over how mathematical operators behave with your tables.
Challenge
EasyWrite 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
xandyset to the provided coordinates - Create a metatable with
__multhat handles multiplication between a vector and a scalar - The
__mulfunction should check which operand is the number and which is the table - Return a new table with
x = vec.x * scalarandy = 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 vectory(number): The y-coordinate of the vectorscalar(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 8The __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 2Try it yourself
function scaleVector(x, y, scalar)
-- Write code here
end
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Advanced Table Iteration
Iterating with pairs()Iterating with ipairs()pairs() vs. ipairs()Recap - Character Sheet4Introduction to Metatables
What is a Metatable?setmetatable & getmetatableThe __index MetamethodThe __newindex MetamethodThe __tostring MetamethodArithmetic Metamethods Part 1Arithmetic Metamethods Part 2Recap - Read-Only Table2More Table Library Functions
table.concat()table construction & unpack()table.sort()Custom Sorting with FunctionsRecap - High Score Board