- WaSQL Wired
- Posts
- Mastering Lua
Mastering Lua
A Comprehensive Guide to Coding in Lua
Lua is a lightweight, embeddable scripting language known for its simplicity, performance, and flexibility. Lua is free and open source and may be used for any purpose, including commercial purposes, at absolutely no cost. You can read up on Lua at https://www.lua.org
While itโs easy to pick up the basics, Lua also offers advanced features that make it a powerful tool for scripting, game development, and embedded systems. This guide is designed to take you from beginner to proficient Lua programmer, with enough depth to serve as a reference for your future projects.
Installation and Setup
To install lua you have two options. You can download and install it yourself from https://www.lua.org/download.html or you can use a package manager:
# install on windows using choco package manager
choco install lua
# install on Ubuntu/Debian
sudo apt install lua5.4
# install on CentOS/Fedora
sudo yum install lua
# install on MacOS
brew install lua
Note: As you go through the following examples there are several Lua-specific operators and syntax elements you should be aware of. You will see many of these used in the examples in this article
-- Lua concatenates using two dots - ..
local fullName = "John" .. " " .. "Doe" -- "John Doe"
-- The pound sign is used to get Length - #
-- length of a string
local length = #"hello" -- 5
-- length of a table
local tableLength = #{ 1, 2, 3, 4 } -- 4
-- You can assign Multiple variables in the same statement
-- Easily swap or assign multiple variables
local a, b = 1, 2 -- a=1, b=2
a, b = b, a -- Now a=2, b=1
-- Logical Operators are and, or, not instead of &&, ||, !
local result = (x > 0 and y < 10)
local value = nil or "default" -- "default"
-- a table in lua is like an array in PHP
-- Different ways to create and access tables
local t = {x = 10, y = 20}
local value = t.x -- Dot notation
local value = t["x"] -- Bracket notation
-- Colons can also be used for Method Call Syntax
local str = "hello"
local upstr1 = string.upper(str) -- Using standard library function
local upstr2 = str:upper() -- Using method call syntax
Ok so lets look at comments. There are two different kinds of comments in Lua - single-line comments and multi-line comments.
-- single line comments
--[[
multi-line comments
can span multiple lines
]]
-- auto-document your code by using comments as shown below:
-- begin function encodeHtml
---@describe Encodes HTML characters that would cause issues in a browser
---@param str string The string to encode
---@return string Encoded HTML string
function encodeHtml(str)
-- If string is empty, just return it
if str == nil or #str == 0 then
return str
end
-- Replace special characters. gsub is part of the standard string module (global substitution)
str = str:gsub('\?', '[[!Q!]]')
str = str:gsub('<', '<')
str = str:gsub('>', '>')
str = str:gsub('"', '"')
str = str:gsub('\?', ' ')
str = str:gsub('[[!Q!]]', '\?')
return str
end
Code Blocks -In Lua, code blocks are typically defined using keywords that mark the beginning and end of a block of code. Code blocks begin with a keyword like function, if, for, while, repeat, or do. Code blocks are closed with end. Indentation is not mandatory but is strongly recommended for readability. Variables declared with local inside a block are only accessible within that block.
-- functional code block
function functionName(parameters)
-- code block starts here
local x = 10
return x
end
-- Conditional Blocks (if-else)
if condition then
-- code block for true condition
print("Condition is true")
elseif another_condition then
-- optional alternative code block
print("Another condition is true")
else
-- optional default code block
print("No conditions were true")
end
-- For Loops
for i = 1, 10 do
print(i)
end
-- While loops
local x=0
while x < 10 do
-- code block runs while condition is true
-- must have a way to eventually exit the loop
x = x + 1
end
-- Repeat-Until Loops
repeat
-- code block runs at least once
-- continues until condition is true
until condition
-- Do-End Blocks (for local scoping)
do
-- create a new local scope
local x = 100
print(x)
end -- x is no longer accessible outside this block
Variables and Data Types. Lua is dynamically typed, meaning you do not have to declare variable types. It handles it for you. However the Basic data types are numbers, strings, Booleans, and Nil. Lua also has a concept of tables. Lua tables are the most fundamental and versatile data structure in Lua. They're essentially associative arrays that can be used as: arrays, dictionaries/hash maps, objects. namespaces, etc.
-- Variables and Basic Types
x = 10 -- integer
y = 9.45 -- number (Lua doesn't distinguish between float/double)
name = "Alice" -- string
is_student = true -- boolean (note lowercase in Lua)
-- Tables (Lua's primary data structure, more flexible than PHP arrays)
-- Empty table
numbers = {}
-- Table with initial values
numbers = {12, 33, 44, 1}
-- Adding elements
table.insert(numbers, 63) -- Adds to end
table.insert(numbers, 1, 5) -- Adds to beginning (1-based index)
-- Removing elements
last = table.remove(numbers) -- Removes and returns last item
first = table.remove(numbers, 1) -- Removes and returns first item
-- Constants (Lua doesn't have built-in constants, use convention)
local MAX_USERS = 100 -- Use local to prevent modification
print(MAX_USERS) -- Output: 100
-- Associative Tables (similar to PHP associative arrays)
d = {name = "Bob", age = 32}
-- Alternative syntax
d = {}
d["name"] = "Bob"
d["age"] = 32
-- Nested tables (similar to nested arrays/dictionaries)
recs = {
{name = "bob", age = 22},
{name = "sam", age = 19}
}
-- Accessing table elements
print(d.name) -- Outputs: Bob
print(d["name"]) -- Also outputs: Bob
print(recs[1].name) -- Outputs: bob
Lua functions for manipulating strings
-- Native Lua String Manipulation Functions
local text = "Hello, World!"
-- Length
print(#text) -- Returns string length
-- Case Conversion
print(text:upper()) -- HELLO, WORLD!
print(text:lower()) -- hello, world!
-- Substring
print(text:sub(1, 5)) -- "Hello"
print(text:sub(-6)) -- "World!"
-- Find (returns start and end index)
local start, end_pos = text:find("World")
print(start, end_pos) -- 8, 12
-- Byte/Char Conversion
print(text:byte(1)) -- ASCII value of first character
print(string.char(65)) -- Character for ASCII value (A)
-- Pattern Matching Find
local pattern_start = text:find("%w+") -- Finds first word
-- Global Substitution
local replaced = text:gsub("World", "Lua") -- Replaces all occurrences
-- Formatting
print(string.format("Name: %s, Number: %d", "Alice", 42))
Loops - Lua supports for, while, and repeat-until loops
-- For loop example
for i = 1, 5 do
print("Iteration: " .. i)
end
-- while loop
local count = 1
while count <= 5 do
print("Count: " .. count)
count = count + 1
end
-- repeat-until example
local x = 1
repeat
print("x: " .. x)
x = x + 1
until x > 5
There are two ways to define functions in Lua - declaration style and expression style
-- Function declaration style
function greet(name)
return "Hello, " .. name .. "!"
end
-- Function expression style
local greet = function(name)
return "Hello, " .. name .. "!"
end
function calculate(a, b)
return a + b, a * b -- Multiple return values
end
local sum, product = calculate(5, 3)
print(sum) -- Outputs: 8
print(product) -- Outputs: 15
-- optional parameters
function greet(name, greeting)
greeting = greeting or "Hello" -- Default value
return greeting .. ", " .. name .. "!"
end
print(greet("Alice")) -- Uses default "Hello"
print(greet("Bob", "Hi")) -- Uses custom greeting
-- Variadic Functions (Variable Number of Arguments)
function sum(...)
local total = 0
local args = {...} -- Converts variable arguments to a table
for _, value in ipairs(args) do
total = total + value
end
return total
end
print(sum(1, 2, 3, 4)) -- Outputs: 10
-- Functions can also take another function as an argument
function apply(func, x, y)
return func(x, y)
end
local function add(a, b) return a + b end
local function multiply(a, b) return a * b end
print(apply(add, 5, 3)) -- Outputs: 8
print(apply(multiply, 5, 3)) -- Outputs: 15
File reading/writing is done via the Lua io module (included by default)
-- reading a file
local file = io.open("example.txt", "r")
if file then
local content = file:read("*a") -- Read entire file
print(content)
file:close()
else
print("Failed to open file")
end
-- writing to a file
local file = io.open("output.txt", "w")
if file then
file:write("Hello, Lua!")
file:close()
else
print("Failed to open file")
end
Lua does not have built-in try/catch error handling like many other programming languages. However it does have a function called pcall (protected call) that you can wrap your function calls in to catch errors.
-- This function will actually execute
local function risky_function()
print("Starting risky function")
error("Intentional error") -- This stops the function's execution
print("This line will never run")
end
-- pcall runs the entire function, not just testing it
local success, error_message = pcall(risky_function)
-- If an error occurs:
-- 1. The function runs until the error
-- 2. The program continues instead of crashing
-- 3. 'success' will be false
-- 4. 'error_message' contains the error description
if not success then
print("Caught an error: " .. error_message)
end
---------- Second Example of using pcall ----------
local function run_database_query(connection, query)
local result = connection:execute(query)
return result
end
-- Using pcall with the database query
local success, result_or_error = pcall(run_database_query, database_connection, "SELECT * FROM users")
if success then
-- Query ran successfully
process_results(result_or_error)
else
-- Handle the error
log_error("Database query failed: " .. result_or_error)
end
-- If successful, success is true and result_or_error contains the query results
-- If an error occurs, success is false and result_or_error contains the error message
Last is includes. Lua includes some modules by default (shown below). Here are a few other really useful modules.
-- Use require to load modules that are not built in.
local json = require("luajson")
--[[
Basic libraries automatically available
string -- String manipulation
math -- Mathematical operations
table -- Table manipulation
io -- Input/Output operations
os -- Operating system interactions
debug -- Debugging facilities
coroutine -- Cooperative multitasking
Useful Third-Party Libraries
Database Connections
luasql: MySQL, PostgreSQL, SQLite connections
luadbi: Database-agnostic interface
JSON Handling
dkjson
luajson
HTTP/Networking
luasocket: Network programming
luasec: SSL support
lua-requests: HTTP requests (similar to Python)
Web Frameworks
Lapis: Web framework
OpenResty: Web platform integrating Nginx and Lua
Advanced Utilities
luafilesystem: File system operations
serpent: Advanced serialization
lualogging: Logging library
]]
Congratulations on making it to the end of this article! Whew! That was a quite a bit to digest. If you're feeling a overwhelmed, I recommend re-reading it a couple more times over the next few days. Repetition will help immensely. When you are ready, try writing some Lua code yourself. Looking forward to hearing what you come up with!
Sponsor: Need some extra storage room in your garage? I have installed two of these and love them! Heavy Duty Metal Garage Ceiling Storage Racks that support 600 lbs! https://www.amazon.com/dp/B0194RLK4Y?tag=fingerpointfo-20

Thanks again for reading. Please like and SHARE. ๐