Lua Cheatsheet

Modules, Errors, and IO

Use this Lua reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Module Pattern

File mathbox.lua:

local M = {}

function M.double(n)
  return n * 2
end

function M.square(n)
  return n * n
end

return M

Use it:

local mathbox = require("mathbox")
print(mathbox.double(7))

require caches modules by name. The module file normally returns a table.

package.path

Lua searches module names through package.path templates.

print(package.path)
package.path = package.path .. ";./lib/?.lua"

A module name like tools.text maps through templates such as tools/text.lua.

error and assert

if not user then
  error("missing user")     -- prefixes "file:line:" where error() ran
end

local function set_port(n)
  if type(n) ~= "number" then
    error("port must be a number", 2)  -- level 2: blame the caller's line
  end
end

error({code = 404})          -- any value can be thrown; non-strings
                             -- get no position prefix

local n = assert(tonumber(text), "expected a number")

error(msg, level): level 1 (default) points at where error was called, level 2 at the function's caller, 0 adds no position. assert(x, msg) returns x (and any extra values) when truthy; otherwise it raises msg.

pcall

local ok, result = pcall(function()
  return risky()
end)

if ok then
  print(result)
else
  print("failed: " .. tostring(result))
end

pcall returns true, ...results on success and false, error_object on failure.

xpcall and Tracebacks

pcall unwinds the stack before returning, so the traceback is already gone. xpcall runs a message handler at the point of the error:

local ok, err = xpcall(risky, debug.traceback)
if not ok then io.stderr:write(err, "\n") end

-- extra arguments after the handler are passed to the function (5.2+)
local ok, result = xpcall(parse, debug.traceback, text)

debug.traceback appends the stack trace to the error message — the standard way to get useful crash logs.

Reading Input

local line = io.read("l")   -- one line, without the newline ("L" keeps it)
local all = io.read("a")    -- rest of input
local n = io.read("n")      -- next number

Since Lua 5.3 the formats are plain "l", "a", "n"; the legacy "*l"/"*a"/"*n" spellings still work everywhere and are required on Lua 5.1/LuaJIT. io.read("n") leaves the newline behind. For mixed line and number reading, many scripts read lines and use tonumber.

Writing Output

print("line")         -- adds newline and tabs between args
io.write("no newline")
io.write("value\n")

Use io.write when exact spacing matters.

Files

local f = assert(io.open("data.txt", "r"))
local text = f:read("a")
f:close()

local out = assert(io.open("out.txt", "w"))
out:write("hello\n")
out:close()

Modes: "r", "w", "a", plus binary variants like "rb" and "wb".

Useful Standard Libraries

LibraryCommon use
mathfloor, ceil, sqrt, random, min, max
stringtext operations and patterns
tableinsert, remove, sort, concat
iostdin, stdout, files
ostime, date, environment, execute
debugintrospection; avoid in normal app code
math.max(3, 9, 2)
os.getenv("HOME")
os.date("%Y-%m-%d")