Functions#
Functions are first-class values in Lua. They are stored in variables, passed as arguments, returned from other functions, and used as table fields (which is how methods work). Lua supports multiple return values, varargs, closures over local state, and tail calls without growing the call stack.
For OOP-by-metatable (where functions become methods), see OOP. For coroutines (functions that yield and resume), see Concurrency.
Definition#
The function keyword is both a statement and an expression.
The statement form is sugar for assigning a function expression.
-- statement form
local function greet(name)
return "hello, " .. name
end
-- expression form (equivalent)
local greet = function(name)
return "hello, " .. name
end
-- table field form (equivalent to t.greet = function ... end)
local t = {}
function t.greet(name)
return "hello, " .. name
end
-- method form (equivalent to t.greet = function(self, name) ... end)
function t:greet(name)
return "hello, " .. self.prefix .. name
end
The colon syntax (t:greet() calling, function t:greet()
defining) implicitly threads self as the first argument.
Parameters#
Lua does not enforce arity. Extra arguments are discarded;
missing arguments are nil.
local function f(a, b, c) return a, b, c end
print(f(1)) --> 1 nil nil
print(f(1, 2, 3, 4)) --> 1 2 3
Default-fill is idiomatic with or.
local function greet(name)
name = name or "operator"
return "hello, " .. name
end
Varargs use ... to receive any number of trailing arguments;
select walks them, {...} collects them, table.pack /
table.unpack round-trip them with a count.
local function log(level, ...)
local args = {...}
for i, v in ipairs(args) do
io.write(level, ":", tostring(v), "\n")
end
end
log("info", "started", 42, true)
Multiple returns#
A function can return any number of values. The receiver picks
how many to bind; extras are discarded, missing slots are
nil.
local function pair()
return 10, 20
end
local a, b = pair() -- a = 10, b = 20
local x = pair() -- x = 10 (second value discarded)
Returned values are truncated to one when the call is not the last expression in its list. Wrap with parentheses to force the same truncation explicitly.
print(pair()) --> 10 20
print((pair())) --> 10 (parens force one)
This rule matters for string.find and other multi-return
stdlib functions when their results flow into other calls.
Closures#
A function value carries the locals visible at the point of its definition. Those locals are upvalues; they live as long as the closure does and are shared across closures that capture the same local.
local function make_counter()
local n = 0
return function()
n = n + 1
return n
end
end
local next1 = make_counter()
local next2 = make_counter()
print(next1(), next1(), next2()) -- 1 2 1
Closures are the foundation of Lua’s “OOP without classes” style; see OOP.
Recursion#
Functions can call themselves. local function f is the
correct form for self-reference; local f = function() f() end
fails because f is still being defined when the body is
captured.
local function factorial(n)
if n <= 1 then return 1 end
return n * factorial(n - 1)
end
Tail calls#
Lua guarantees proper tail calls: return f(args) does not
grow the stack. Mutual recursion at arbitrary depth is safe as
long as the recursive call is in tail position.
local function loop(n)
if n == 0 then return "done" end
return loop(n - 1) -- tail call; constant stack
end
print(loop(1000000))
A call is in tail position only if its result is what the function returns, with nothing else in the way (no arithmetic, no parentheses, no extra arguments to discard).
References#
Syntax for the lexical surface
functionandreturnlive in.Variables for upvalues and the scope rules behind closures.
OOP for methods, metatables, and OOP-by-table.
Concurrency for
coroutine.yieldand resumable functions.