Lua Basics

Published March 2, 2020

GuideBlogLuaCoding

Basic Syntax and Data Types

Basic Syntax and Data Types

Lua is a lightweight and easy to learn programming language. In this section, we will cover the basic structure of a Lua script, as well as the different data types available and how to manipulate them.

Script Structure

A Lua script is a plain text file with the .lua file extension. The script is executed from top to bottom, and it can contain a combination of statements, comments, and functions.

Statements

Statements are commands that perform a specific action, such as assigning a value to a variable or calling a function.
-- This is a statement that assigns the value "hello" to the variable "greeting" greeting = "hello"

Comments

Comments are used to add notes or explanations to the code and are ignored by the interpreter. In Lua, comments are created using double dashes (--).
-- This is a comment and will be ignored by the interpreter greeting = "hello"

Tip: It's a great practice to leave comments around your code to explain what it does, for not only yourself but others.

-- Function to check pal's health function checkPalHealth() -- Get pal using getPal function local pal = getPal("anubis") -- Return pal's health return pal.health end

Variables and Functions

Variables and Functions

In Lua, variables are used to store and manipulate data, and functions are used to organize and reuse code.

Variables

In Lua, variables are declared using the `local` keyword or without it. It's recommended to use the local keyword when declaring a variable, as it limits the scope of the variable to the current function or file, and prevents accidental global variable assignments.
-- Declaring a variable local x = 5 -- Declaring a variable without the `local` keyword y = 10
Lua supports several data types, including numbers, strings, booleans, and tables.
-- Declaring a number variable local age = 25 -- Declaring a string variable local name = "John" -- Declaring a boolean variable local isValid = true -- Declaring a table variable local myTable = {1, 2, 3}

Functions

In Lua, functions are declared using the function keyword and can be called using the function name followed by parentheses.
-- Declaring a function function sayHello() print("Hello!") end -- Calling a function sayHello()
Functions can also take parameters and return values.
-- Declaring a function with parameters function add(x, y) return x + y end -- Calling a function with arguments result = add(5, 10)
Functions can be stored in variables and passed as arguments to other functions.
-- Storing a function in a variable local myFunction = function() print("Hello!") end -- Passing a function as an argument otherFunction(myFunction)

Flow Control

Flow Control

In Lua, flow control statements are used to control the flow of execution of a script. These include `if`, `else`, `elseif`, `for`, `while`, and `repeat` statements.

If-Else Condition

The `if` statement is used to check if a certain condition is true and execute a block of code if it is. The `else` statement is used as an alternative if the condition is not true.
-- If-else statement local x = 5 if x > 10 then print("x is greater than 10") else print("x is less than or equal to 10") end

Elseif Condition

The `elseif` statement is used to check multiple conditions. If the first condition is not true, the script will check the next one, and so on, until a true condition is found or the end of the script is reached.
-- Elseif statement local x = 5 if x > 10 then print("x is greater than 10") elseif x < 0 then print("x is less than 0") else print("x is between 0 and 10") end

For Loop

The `for` loop is used to iterate over a range of numbers or elements in an array or table. The loop variable is declared and initialized before the loop, and the loop will continue until the end condition is met.
-- For loop for i = 1, 10 do print(i) end

While Loop

The `while` loop is used to execute a block of code repeatedly as long as a certain condition is true.
-- While loop local x = 5 while x > 0 do print(x) x = x - 1 end

Repeat Until

The `repeat` statement is used to execute a block of code repeatedly until a certain condition is met. The code block is executed at least once before the condition is checked.
-- Repeat until local x = 5 repeat x = x - 1 print(x) until x == 0

Tables and Metatables

Tables and Metatables

In Lua, tables are a fundamental data structure used to store and organize data. A table is a collection of key-value pairs, where each key is unique within the table. Tables can be used as arrays, dictionaries, objects, or a combination of these.

Creating a Table

To create a table, you can use curly braces `` and separate the key-value pairs with commas. Keys can be either numbers or strings, and values can be any Lua data type, including other tables.
-- Creating a table local myTable = { ["name"] = "John", ["age"] = 25, [3] = "hello", -- Tables can be used as values of other tables ["nestedTable"] = { ["key"] = "value" } }

Accessing Table Elements

You can access the elements of a table using the table name followed by the key in square brackets `[]`.
-- Accessing table elements print(myTable["name"]) -- Output: John print(myTable.name) -- Output: John print(myTable[3]) -- Output: hello print(myTable.nestedTable.key) -- Output: value

Metatables

Metatables are used to define the behavior of a table when certain operations are performed on it. A metatable is a table that can be set as the metatable of another table. The metatable contains metamethods, which are functions that define the behavior of the table when certain operations are performed on it.
-- Creating a metatable local myMetatable = { __add = function(table1, table2) local newTable = {} for k, v in pairs(table1) do newTable[k] = v end for k, v in pairs(table2) do newTable[k] = v end return newTable end } -- Setting the metatable setmetatable(myTable, myMetatable) -- Using the metamethod local myOtherTable = { ["city"] = "New York", ["country"] = "USA" } local myCombinedTable = myTable + myOtherTable print(myCombinedTable.name) -- Output: John print(myCombinedTable.city) -- Output: New York

Object-Oriented Programming

Object-Oriented Programming in Lua

While Lua doesn't have built-in class support, we can implement OOP patterns using tables and metatables. This creates a powerful and flexible object system.

Creating Classes

-- Define a class local Player = {} Player.__index = Player function Player.new(name, health) local self = setmetatable({}, Player) self.name = name self.health = health return self end function Player:takeDamage(amount) self.health = self.health - amount end -- Creating an instance local player = Player.new("Hero", 100) player:takeDamage(10) print(player.health) -- Output: 90

Inheritance

-- Base class local Entity = {} Entity.__index = Entity function Entity.new(name) local self = setmetatable({}, Entity) self.name = name return self end -- Derived class local Monster = setmetatable({}, {__index = Entity}) Monster.__index = Monster function Monster.new(name, damage) local self = setmetatable(Entity.new(name), Monster) self.damage = damage return self end

Error Handling and Debugging

Error Handling and Debugging

Lua provides robust error handling mechanisms to help you write more reliable code and track down issues effectively.

Protected Calls

-- Using pcall for safe execution local success, result = pcall(function() -- Potentially dangerous code error("Something went wrong!") end) if not success then print("Error caught: " .. result) end

Custom Error Handling

-- Creating and handling custom errors function divide(a, b) if b == 0 then error("Division by zero!", 2) end return a / b end local success, result = pcall(divide, 10, 0) if not success then print("Error in division: " .. result) end

Debug Library

-- Using the debug library local function trace() local level = 2 local info = debug.getinfo(level, "Sl") while info do print(string.format("%s:%d", info.short_src, info.currentline)) level = level + 1 info = debug.getinfo(level, "Sl") end end function someFunction() trace() -- Print stack trace end

Code Standards and Organization

Code Standards and Organization

Writing clean, maintainable Lua code involves following consistent patterns and conventions. Here's how to structure your code professionally.

File Organization

-- config.lua local Config = { VERSION = "1.0.0", MAX_PLAYERS = 10, DEBUG_MODE = true } return Config -- player.lua local Player = {} local Config = require("config") function Player.new(name) return { name = name, health = 100, maxPlayers = Config.MAX_PLAYERS } end return Player

Naming Conventions

Follow these naming patterns for clear, readable code:
PascalCase for modules and classes (PlayerManager, GameState)
camelCase for functions and variables (getCurrentPlayer, playerCount)
UPPERCASE for constants (MAX_HEALTH, DEFAULT_SPEED)
Use descriptive, meaningful names (calculateDamage, isPlayerAlive)
-- Module/Class names (PascalCase) local PlayerManager = {} local GameState = {} -- Variables and functions (camelCase) local playerCount = 0 local function getCurrentPlayer() return activePlayer end -- Constants (UPPERCASE) local MAX_HEALTH = 100 local DEFAULT_SPEED = 5 -- Clear, descriptive names local isPlayerAlive = true local function calculateDamage(baseDamage, armor) return baseDamage * (1 - armor) end

Documentation Standards

--- Player class representing a game character -- @class Player -- @field name string The player's display name -- @field health number Current health points local Player = {} --- Creates a new Player instance -- @param name string The player's name -- @param health number Initial health value -- @return Player The new player instance function Player.new(name, health) local self = setmetatable({}, Player) self.name = name self.health = health return self end --- Applies damage to the player -- @param amount number The amount of damage to apply -- @return number The remaining health function Player:takeDamage(amount) self.health = math.max(0, self.health - amount) return self.health end