Skip to main content

Functions & Closures

Function syntax

Named function

function add(a, b)
return a + b
end

Anonymous function (lambda)

local add = function(a, b)
return a + b
end

Method syntax (adds implicit self)

function obj:greet(name)
print(self.name .. " says hi to " .. name)
end
-- Equivalent to:
function obj.greet(self, name) ... end

-- Call with colon syntax:
obj:greet("Lua") -- passes obj as first arg

Parameters

Regular parameters

function f(a, b, c)
print(a, b, c)
end
f(1, 2, 3) -- 1 2 3
f(1, 2) -- 1 2 nil
f(1, 2, 3, 4) -- 1 2 3 (extra discarded)

Default values (idiom)

LuaLuaA lightweight, embeddable scripting language used as the primary scripting language in FiveM server development. has no built-in defaults. Use or:

function greet(name)
name = name or "World"
print("Hello, " .. name)
end

Multiple return values

function swap(a, b)
return b, a
end

local x, y = swap(1, 2) -- x=2, y=1

When multiple returns are kept/discarded

function multi() return 1, 2, 3 end

-- Kept: at end of expression list
local a, b, c = multi() -- 1, 2, 3
print(multi()) -- 1, 2, 3
return multi() -- passes all 3

-- Discarded: in middle of expression list
local a, b = multi(), 99 -- a=1, b=99 (2,3 discarded)
local a = (multi()) -- a=1 (parens force single value)

Varargs

function f(a, b, ...)
local args = {...} -- capture as table
print(select("#", ...)) -- count of varargs
print(...) -- pass through
end

f(1, 2, 3, 4, 5)
-- args = {3, 4, 5}
-- select("#", ...) = 3

select function

select(i, ...) -- returns args from i onward
select("#", ...) -- returns count of varargs

print(select(3, "a", "b", "c", "d")) -- c d

Closures

Functions can capture outer local variables (upvalues). The captured variable persists even after the outer scope ends.

function counter()
local n = 0
return function()
n = n + 1
return n
end
end

local c = counter()
print(c()) -- 1
print(c()) -- 2
print(c()) -- 3

Shared upvalues

Multiple closures can share the same upvalue:

function make_getter_setter()
local value = 0
return {
get = function() return value end,
set = function(v) value = v end,
}
end

local gs = make_getter_setter()
gs.set(42)
print(gs.get()) -- 42

First-class functions

Functions are values — store in tables, pass as args, return from functions.

-- Store in table
local ops = {
add = function(a, b) return a + b end,
sub = function(a, b) return a - b end,
}
print(ops.add(1, 2)) -- 3

-- Higher-order function
function apply(f, x, y)
return f(x, y)
end
print(apply(ops.mul or ops.add, 3, 4)) -- 7

-- Sorting with custom comparator
local t = {3, 1, 4, 1, 5}
table.sort(t, function(a, b) return a < b end)

pcall and protected calls

local ok, result = pcall(function()
error("something went wrong")
end)
print(ok) -- false
print(result) -- something went wrong

See Error-Handling for full details.


Tail calls

A tail call occurs when a function call is the last action before return. LuaLuaA lightweight, embeddable scripting language used as the primary scripting language in FiveM server development. optimizes this to avoid growing the stack.

function factorial(n, acc)
acc = acc or 1
if n <= 1 then return acc end
return factorial(n - 1, n * acc) -- tail call
end

print(factorial(100000)) -- no stack overflow

Requirements for tail call:

  • Call must be the last action in the function
  • No further operations after the call
  • Cannot be in a return f(), g() (that's multiple returns)

Function properties

PropertyValue
Type"function"
EqualityBy reference (same closure = same)
ComparisonOnly == and ~= (no <)
Garbage collectedYes (with upvalues)