Skip to content
Lesson 14 of 18

Step 1 of 5 · Reading · ~4 min

Learn

Functions

Defining Functions

A function in Lua is a value, exactly like a number or a string. function add(a, b) ... end is not a special declaration form — it is sugar for building an anonymous function and assigning it to the name add.

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

local plus = add
print(plus(2, 3))

--> 5

Because functions are values, you can store them in tables, hand them to other functions, and return them from functions. That is what the Closures lesson builds on, and it is where most of Lua's expressive power lives.

Why write local function?

Without local, a function name is a global, with every problem the Variables lesson described. With it, the name is confined to the enclosing block.

There is a second reason, and it is easy to trip over: recursion.

✓ the local exists before the body is compiled

local function fact(n)
    if n <= 1 then return 1 end
    return n * fact(n - 1)
end
print(fact(5))

--> 120

✗ the same code written the long way

local fact = function(n)
    if n <= 1 then return 1 end
    return n * fact(n - 1)
end
print(fact(5))

--> lua: attempt to call a nil value (global 'fact')

In the second version the name fact is not in scope yet while the body is being compiled, so the recursive call is compiled as a global lookup, and that global does not exist. local function f is defined to declare the local first and assign second, precisely so recursion works.

Arguments are ordinary locals

Parameters are plain local variables filled in from the call site. Extra arguments are discarded; missing ones arrive as nil. Lua never complains about the count.

local function greet(name, punct)
    print(name .. (punct or "!"))
end

greet("Ada")
greet("Ada", "?")
greet("Ada", "?", "ignored")

--> Ada!
--> Ada?
--> Ada?

That silence cuts both ways: the or default is a clean one-liner, and a typo that drops an argument gives you a nil several lines later instead of an error at the call.

Returning more than one value

A Lua function returns any number of values, and the caller decides how many to keep.

local function bounds(a, b)
    if a < b then return a, b end
    return b, a
end

local lo, hi = bounds(9, 4)
print(lo .. " " .. hi)

--> 4 9

The rule that catches everybody is adjustment: a call keeps all of its values only when it is the last item in a list. Anywhere else it is trimmed to exactly one.

local function two()
    return 1, 2
end

print(two())
print(two(), 99)
print((two()))

Output (the gaps are TAB characters):

1	2
1	99
1

The first call is last in the argument list, so both values survive. The second is not last, so only 1 gets through. The third is wrapped in parentheses, which is the explicit way of saying "one value, please".

Assignment follows the same rule, and surplus names get nil:

local a, b, c = two()
print(c)

--> nil

Variable arguments

Three dots in the parameter list collect everything the caller passed.

local function total(...)
    local sum = 0
    for _, v in ipairs({...}) do
        sum = sum + v
    end
    return sum
end

print(total(1, 2, 3, 4))

--> 10

{...} packs the arguments into a table. Watch for a nil among them: it creates a hole and ipairs stops there, so use select("#", ...) when you need the true count.

Your exercise

Min and Max asks you to fill in minmax(t), which takes a table of numbers and returns two values — the smallest and the largest. The starter reads the input and already prints lo .. " " .. hi, so leave that line exactly as it is.

Two mistakes the grader will catch. Seeding the search with zero, local lo, hi = 0, 0, prints 0 5 for the visible test containing 3, 1, 4, 1, 5, because 0 is smaller than every number in the list and was never in it. Seed both from t[1]. And returning a single value leaves hi as nil, so the starter's own print line dies with attempt to concatenate a nil value — the return statement needs both names.

Up nextClosuresFunctions

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…