paulgorman.org/technical

Lua

(January 2017)

Lua is tiny, light-weight scripting language. It’s suitable for embedding in other programs.

Lua has a REPL.

For some reason, Lua 5.3, the current version, must be invoked as lua5.3 rather than lua. (EDIT: The unfortunate reason, I suspect, is that Lua is effectively forked, with the popular and much faster LuaJIT implementation frozen at Lua 5.1.)

Debian provides many Lua packages, including: lua5.3 lua5.1 luajit.

These notes cover mostly Lua 5.1.

Single-line Lua comments start with two dashes:

-- Like this.

Multi-line comment start with two dashes and two left brackets, and continue until two right brackets:

--[[
This is
a multi-line
comment.
--]]

Lua one-liners are a thing:

$ lua5.3 -e "print(22.8 * 3.24)"

Variable, Values, and Types

Lua is dynamically typed — variables don’t have types, only values have types. Variables in Lua are global unless explicitly declared local. Variables declared with the local keyword are scoped to their block:

while i <= x do
	a_global_variable = "foo"  -- Global because it wasn't declared with the `local` keyword
	local x = i*2  -- Local to the while body
	print(x)  --> 2, 4, 6, 8, ...
	i = i + 1
end
print(a_global_variable)  -- Still in scope

Command-line argument to a lua script are passed in a table called arg. (“Tables” are associative arrays, like Python’s dictionaries.)

print(arg[0])  -- The script name
print(arg[1])  -- The first command-line argument

Tables and strings are indexed from 1 rather than 0.

The eight basic types are: nil, boolean, function, number, string, thread, table, and userdata. Types are dynamic. An undefined variable has type nil.

The type function returns the type of value given:

print(type("Hello world"))  --> string

As for boolean values, nil and false evaluate as false; all other values evaluate true, including zero and empty strings.

Tables:

t = {}  -- create a table and store its reference in `a'
bubble = "snail"
t[bubble] = 10  -- new entry, with key="snail" and value=10
t[30] = "thirty"  -- new entry, with key=30 and value="thirty"
print(t["snail"])  --> 10
bubble = 30
print(t[bubble])  --> "thirty"
t["snail"] = t["snail"] + 1     -- increments entry "snail"
print(t["snail"])    --> 11
print(t.snail)  --> 11, dot notation

A function:

function my_function(my_num)
	--[[--
	An example function

	@Parameter: my_num
		Just a sample argument

	@Returns: The argument squared
	--]]--
	local result = my_num * my_num
	return result
end

Because functions are a first-class type, they can be stored in variables, passed as arguments, returned from functions, etc.

The userdata type is for storing raw C data.

String literals can be surrounded by double or single quotes, or by [[long brackets]].

The thread type holds the independent execution threads used for coroutines. Lua threads do not necessarily correspond to OS threads.

Operators

The == operator tests equality. The ~= operator tests inequality (not equals).

Lua has the logical operator and, or, and not.

if not x then x = v end

The string concatenation operator is .. (two dots).

Logical operators include and, or, and not, like:

nil or 'foo'    --> 'foo'

# is the “length of” operator:

#'foobar'    --> 6

Statements, Loops, and Structures

If statements:

if op == "+" then
	r = a + b
elseif op == "-" then
	r = a - b
else
	error("invalid operation")
end

Repeat statements:

-- print the first non-empty line
repeat
	line = os.read()
until line ~= ""
print(line)

While loop:

local i = 1
while a[i] do
	print(a[i])
	i = i + 1
end

For loop:

for var = exp1, exp2, exp3 do
  something
end

That loop executes once for each value of var from exp1 to exp2, using exp3 as the step to increment var.

for i = 10, 1, - 1 do
	print(i)
end

Unlike most places in Lua, the control variable (e.g. i) is implicitly local to the for block. Use break to prematurely exit a for loop.

Modules

The module file:

local mymodule = {}

function mymodule.foo()
	print("Hello World!")
end

return mymodule

A script using the module:

mymodule = require "mymodule"
mymodule.foo()

LuaRocks is a package manager for lua modules.

If performance become a problem, the LuaJIT compiler if much, much faster. However, at this time, the LuaJIT author says he’ll never support a version of Lua newer than 5.1.