Luawe the Wayfarer Engine's scripting language All pages

Functions

A function is a piece of script with a name, to be used again and again. print is one, and so is things.find. This page is about writing your own.

Making and calling one

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

greet("Sky")
greet("Moon")

It prints

Hello, Sky!
Hello, Moon!

name is the function's parameter: a variable that holds whatever the function was called with. Calling a function is writing its name with the values in brackets.

local function keeps the function to the block it is written in, like local does for a variable. Without local it is a global of the script.

Giving something back

return ends the function and hands a value back to whoever called it:

local function area(width, height)
    return width * height
end

print(area(3, 4))

It prints

12

A function can give back several values, and several variables can take them:

local function middle(thing)
    return thing.x + thing.w / 2, thing.y + thing.h / 2
end

local x, y = middle({ x = 2, y = 4, w = 6, h = 2 })
print(x, y)

It prints

5 5

return on its own leaves a function early and gives nothing back.

Too few values, too many

Calling a function with fewer values than it has parameters is fine: the rest are nil. Extra values are dropped. This makes parameters with a fallback easy:

local function shout(text, times)
    times = times or 1
    print(string.rep(text .. "!", times, " "))
end

shout("go")
shout("go", 3)

It prints

go!
go! go! go!

When a call that gives several values is not the last thing in a list, only its first value is used:

local function two()
    return 1, 2
end

print(two(), "end") -- two() is cut to its first value
print("start", two())

It prints

1 end
start 1 2

Any number of values

Three dots take whatever values a function is called with. { ... } makes a list of them, and select("#", ...) counts them:

local function sum(...)
    local total = 0
    for _, n in { ... } do
        total += n
    end
    return total, select("#", ...)
end

print(sum(1, 2, 3))

It prints

6 3

Functions are values

A function is a value like a number or a string. It can be kept in a variable, put in a table, and handed to another function. A function written without a name, right where it is needed, is how most events are answered:

level.beat:connect(function(beat)
    print("beat " .. beat)
end)

And it is how a list is sorted your way:

local scores = { 40, 90, 15 }
table.sort(scores, function(a, b)
    return a > b -- the bigger one first
end)
print(table.concat(scores, " "))

It prints

90 40 15

Functions remember

A function can use the variables around it, and it keeps them for as long as it lives, even after the block they were made in has ended:

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

local tick = counter()
print(tick(), tick(), tick())

It prints

1 2 3

Each call of counter makes a count of its own, so two counters do not disturb each other.

Functions in tables

A table can hold functions, which is how the libraries are built: math.floor is the function floor in the table math. You can do the same:

local door = { open = false }

function door.toggle()
    door.open = not door.open
    print(door.open and "open" or "shut")
end

door.toggle()
door.toggle()

It prints

open
shut

The colon

Written with a colon, a function gets the table it was called on as a hidden first parameter named self. That lets one function serve many tables:

local Door = {}
Door.__index = Door

function Door.new(name)
    return setmetatable({ name = name, open = false }, Door)
end

function Door:toggle()
    self.open = not self.open
    print(self.name .. " is " .. (self.open and "open" or "shut"))
end

local front, back = Door.new("front"), Door.new("back")
front:toggle()
back:toggle()
front:toggle()

It prints

front is open
back is open
front is shut

front:toggle() is short for front.toggle(front). The game's own values work this way too: door:tween(...), player:revive(), event:connect(...). Call those with a colon.

The line Door.__index = Door and setmetatable are explained under lists and tables.

A function calling itself

A function may call itself, as long as it stops somewhere:

local function countdown(n)
    if n == 0 then
        print("go!")
        return
    end
    print(n)
    countdown(n - 1)
end

countdown(3)

It prints

3
2
1
go!

Next: lists and tables.