Beginner's Guide to Lua

SwastikSwastik
13 min read

Lua is a lightweight, high-level programming language that was originally designed for embedding into applications. In essence, it’s meant to be easily integrated into larger software systems, where it can serve as a scripting or extension language.

Personally, Lua is one of my favorite programming languages. Not only is it lightweight and robust, it also has an extremely beginner-friendly syntax and retains high speed functionality and utilities. Lua is extensively used in the fields of embedded scripting, game development and extensibility of software due to its compatibility with C and other languages.

Installation on Windows

The first step to start scripting in Lua is, of course, installing Lua on your system. There are several ways to install Lua on your Windows system:

Binary Releases:

Install Lua using the open binary releases from http://luabinaries.sourceforge.net/.

Select the version you wish to download. Select the download option for your 32-bit or 64-bit device accordingly. Extract the downloaded .zip folder in an accessible location in a folder. It should contain three executable .exe files and a DLL .dll file. Add the Lua executable to your system’s environment variable PATH. To do this, follow these steps:

  1. Search ‘env’ and select the ‘Edit the system environment variables option’.

  2. Click on the ‘Environment Variables’ option

  3. Click on ‘Path’, and click ‘Edit’

  4. Click on ‘Browse’, and add the executable (or the folder containing the executable) to the system’s path variable. Click on ‘OK’ when added. Save and exit.

Using “winget” package manager :

This is perhaps the easiest method to install Lua on a Windows system. The winget command is available by default on Windows 11 systems. The winget package manager can be installed on previous versions of Windows as well. To install Lua, open cmd and type:

winget install "Lua for Windows"

Using MSYS2:

If you want to install Lua, and you have MSYS2 installed, run this command:

pacman -S mingw-w64-x86_64-lua

Verify Installation

Verify whether Lua has been installed in your system by running the command lua -v. This should display the version of Lua installed in your system:

Lua works in the terminal, but I would recommend using an IDE to make your experience better.

If you are using VSCode, don’t forget to install the Lua extension.

Getting Started

Printing your very first message

To print your very first message using Lua, create a file filename.lua. Then write the following code:

print("Hello World!")

When you run this code, the terminal should display Hello World!. This is because the print statement is used to display arguments as output. Next, to test out escape sequences, try out the following:

print("Demonstrating escape sequences in Lua:\nNewline: This is a new line\nTab: This is\ta tab\nBackslash: This is a backslash \\\nDouble quote: This is a \"quoted\" text\nSingle quote: This is a \'quoted\' text")

Escape sequences are typically used to specify actions such as carriage returns and tab movements on terminals. The given Lua code demonstrates the use of escape sequences in strings. Here's a breakdown of each part:

  • \n: This is the newline escape sequence. It moves the cursor to the next line. In the output, "Newline: This is a new line" will appear on a new line after "Demonstrating escape sequences in Lua:".

  • \t: This is the tab escape sequence. It inserts a horizontal tab space. In the output, "Tab: This is" will be followed by a tab space before "a tab".

  • \\: This is the escape sequence for a backslash. Since the backslash is used as an escape character, you need to use two backslashes to display a single backslash in the output. "Backslash: This is a backslash " will show a single backslash.

  • \": This escape sequence allows you to include a double quote within a string. In the output, "Double quote: This is a "quoted" text" will display the text with double quotes around "quoted".

  • \': This escape sequence allows you to include a single quote within a string. In the output, "Single quote: This is a 'quoted' text" will display the text with single quotes around "quoted".

When you run this code, it will print the following:

Comment Lines

In Lua, comments are useful for explaining code, making notes, or temporarily disabling code during development. There are two types of comments in Lua: single-line comments and multi-line (block) comments.

  1. Single-line comments: These are initiated with two hyphens (--). Everything following the -- on that line is considered a comment and is ignored by the Lua interpreter.

    Example:

     -- This is a single-line comment
     print("Hello, World!")  -- This is another comment
    
  2. Multi-line (block) comments: These are enclosed between --[[ and ]]. Everything between these markers is considered a comment, allowing for comments that span multiple lines.

    Example:

     --[[
     This is a multi-line comment.
     It can span multiple lines.
     ]]
     print("Hello, World!")
    

Variables

In Lua, a variable is a symbolic name associated with a value and is used to store data that can be referenced and manipulated in a program. Variables in Lua are dynamically typed, meaning that you don't need to declare the type of a variable when you create it. The type is determined automatically based on the value assigned to the variable.

Variables in Lua are typically declared using the local keyword for local scope, or without it for global scope. For example:

local x = 10  -- Local variable
y = "Hello"   -- Global variable

Variables act as a reference for stored data which can be used to perform tasks. The data stored in variables can be modified, for example, the variable in the snippet below gets updated to store “Bye”, overwriting “Hello”.

x = "Hello" -- Updates x to store "Hello"
print(x) -- Prints "Hello"
x = "Bye" -- Updates x to store "Bye"
print(x) -- Prints "Bye"

Arithmetic Operations

Lua supports a variety of arithmetic operations, which are used to perform mathematical calculations. The basic arithmetic operators in Lua include:

  1. Addition (+): Adds two numbers.

     local sum = 5 + 3  -- Result is 8
    
  2. Subtraction (-): Subtracts the second number from the first.

     local difference = 5 - 3  -- Result is 2
    
  3. Multiplication (*): Multiplies two numbers.

     local product = 5 * 3  -- Result is 15
    
  4. Division (/): Divides the first number by the second.

     local quotient = 5 / 3  -- Result is approximately 1.6667
    
  5. Floor Division (//): Divides the first number by the second and rounds down to the nearest integer.

     local floorDiv = 5 // 3  -- Result is 1
    
  6. Modulus (%): Returns the remainder of the division of the first number by the second.

     local remainder = 5 % 3  -- Result is 2
    
  7. Exponent (^): Raises the first number to the power of the second.

     local power = 5 ^ 3  -- Result is 125
    

Strings

In Lua, strings are sequences of characters used to represent text. They are immutable, meaning once a string is created, it cannot be changed. Lua provides several operations and functions to work with strings:

  1. Concatenation: Strings can be concatenated using the .. operator. For example, "Hello" .. " World" results in "Hello World".

  2. Length: The length of a string can be obtained using the # operator. For example, #("Hello") returns 5.

  3. String Functions: Lua offers a variety of built-in string functions, such as:

    • string.upper(): Converts all characters in a string to uppercase.

    • string.lower(): Converts all characters in a string to lowercase.

    • string.sub(): Extracts a substring from a string.

    • string.find(): Searches for a pattern in a string and returns the start and end indices.

    • string.format(): Formats strings in a manner similar to printf in C.

  4. Escape Sequences: Strings can include escape sequences like \n for newline, \t for tab, and \\ for a backslash.

  5. String Literals: Strings can be defined using single or double quotes. For multi-line strings, Lua uses double square brackets [[ ]].

     -- Sample string
     local sampleString = "This is a beginner's guide to Lua!"
    
     -- String length
     local length = #sampleString
     print("Length: " .. length)  -- Output: Length: 34
    
     -- Convert to uppercase
     local upperString = string.upper(sampleString)
     print("Uppercase: " .. upperString)  -- Output: Uppercase: THIS IS A BEGINNER'S GUIDE TO LUA!
    
     -- Convert to lowercase
     local lowerString = string.lower(sampleString)
     print("Lowercase: " .. lowerString)  -- Output: Lowercase: this is a beginner's guide to lua!
    
     -- Substring extraction
     local subString = string.sub(sampleString, 11, 19)
     print("Substring: " .. subString)  -- Output: Substring: beginner's
    
     -- Find a pattern
     local startIndex, endIndex = string.find(sampleString, "guide")
     print("Found 'guide' at: " .. startIndex .. " to " .. endIndex)  -- Output: Found 'guide' at: 23 to 27
    
     -- String formatting
     local formattedString = string.format("The number is: %d", 42)
     print("Formatted String: " .. formattedString)  -- Output: Formatted String: The number is: 42
    
     -- Reverse a string
     local reversedString = string.reverse(sampleString)
     print("Reversed: " .. reversedString)  -- Output: Reversed: !auL ot ediuG s'reninnigeb a si sihT
    
     -- Repeat a string
     local repeatedString = string.rep("Lua ", 3)
     print("Repeated: " .. repeatedString)  -- Output: Repeated: Lua Lua Lua 
    
     -- Gsub (global substitution)
     local replacedString = string.gsub(sampleString, "Lua", "Programming")
     print("Replaced: " .. replacedString)  -- Output: Replaced: This is a beginner's guide to Programming!
    

Decision Blocks

In Lua, decision blocks are used to control the flow of execution based on certain conditions. The primary decision-making structure in Lua is the if statement, which can be used in combination with else and elseif to create complex conditional logic.

  1. If Statement: Executes a block of code if a specified condition is true.

     if condition then
         -- code to execute if condition is true
     end
    
  2. If-Else Statement: Provides an alternative block of code to execute if the condition is false.

     if condition then
         -- code to execute if condition is true
     else
         -- code to execute if condition is false
     end
    
  3. If-Elseif-Else Statement: Allows for multiple conditions to be checked in sequence.

     if condition1 then
         -- code to execute if condition1 is true
     elseif condition2 then
         -- code to execute if condition2 is true
     else
         -- code to execute if none of the above conditions are true
     end
    

    Tables

    In Lua, tables are the primary data structure and are used to implement arrays, dictionaries, and other complex data types. Here's a detailed overview of tables and their implementation:

    1. Creation: Tables are created using curly braces {}. For example, local myTable = {} creates an empty table. You can also initialize tables with values, like local myTable = {1, 2, 3}.

    2. Indexing: Tables can be indexed using numbers or strings. Numeric indices are typically used for arrays, while string indices are used for dictionaries. For example, myTable[1] = "Hello" or myTable["key"] = "value".

    3. Arrays: Lua tables can function as arrays, where indices are consecutive integers starting from 1. For example, local array = {10, 20, 30}. You can access elements using their indices, like array[1].

    4. Dictionaries: Tables can also function as dictionaries (or associative arrays), where keys are strings. For example, local dict = {name = "Lua", type = "language"}. Access elements using keys, like dict["name"].

    5. Nested Tables: Tables can contain other tables, allowing for the creation of complex data structures. For example, local nestedTable = {inner = {1, 2, 3}}.

    6. Functions: Lua provides several built-in functions to work with tables, such as table.insert, table.remove, table.sort, and table.concat. These functions help manipulate table data efficiently.

    7. Implementation: Internally, Lua tables are implemented as hash tables. This allows for efficient storage and retrieval of key-value pairs. Lua handles the resizing of tables automatically as elements are added or removed.

       -- Creating a table
       local myTable = {1, 2, 3, name = "Lua", type = "language"}
      
       -- Indexing and modifying table elements
       myTable[1] = 10
       myTable["version"] = 5.4
      
       -- Adding a new key-value pair
       myTable.creator = "Author"
      
       -- Printing table elements
       print("First element: " .. myTable[1])  -- Output: First element: 10
       print("Name: " .. myTable.name)         -- Output: Name: Lua
       print("Version: " .. myTable.version)   -- Output: Version: 5.4
      
       -- Iterating over a table using pairs
       print("Table contents:")
       for key, value in pairs(myTable) do
           print(key .. ": " .. tostring(value))
       end
      
       -- Nested tables
       local nestedTable = {
           inner = {1, 2, 3}
       }
      
       -- Accessing nested table elements
       print("First element of inner table: " .. nestedTable.inner[1])  -- Output: 1
      
       -- Using table functions
       table.insert(myTable, "new element")
       print("After insertion:")
       for key, value in pairs(myTable) do
           print(key .. ": " .. tostring(value))
       end
      
       table.remove(myTable, 1)
       print("After removal:")
       for key, value in pairs(myTable) do
           print(key .. ": " .. tostring(value))
       end
      
       -- Sorting a table
       local numbers = {3, 1, 4, 1, 5}
       table.sort(numbers)
       print("Sorted numbers:")
       for i, value in ipairs(numbers) do
           print(value)
       end
      
       -- Concatenating table elements
       local concatenated = table.concat(numbers, ", ")
       print("Concatenated numbers: " .. concatenated)  -- Output: Concatenated numbers: 1, 1, 3, 4, 5
      

      Loops

      In Lua, loops are used to execute a block of code repeatedly. Lua provides several types of loops to handle different looping requirements:

      1. while Loop: This loop continues to execute as long as a specified condition is true. It checks the condition before executing the loop body.

         local i = 1
         while i <= 5 do
             print("Iteration: " .. i)
             i = i + 1
         end
        
      2. repeat Loop: This loop is similar to the while loop, but it checks the condition after executing the loop body, ensuring that the loop body is executed at least once.

         local i = 1
         repeat
             print("Iteration: " .. i)
             i = i + 1
         until i > 5
        
      3. for Loop: This loop is used for numeric iteration, where you know the number of iterations in advance. It includes an initialization, a condition, and an increment.

         for i = 1, 5 do
             print("Iteration: " .. i)
         end
        

        This loop is used to iterate over elements in a table using the pairs or ipairs functions.

         local array = {10, 20, 30}
         for index, value in ipairs(array) do
             print("Index: " .. index .. ", Value: " .. value)
         end
        

Functions

In Lua, functions are first-class values, meaning they can be stored in variables, passed as arguments, and returned from other functions. Here's a brief overview of functions in Lua:

  1. Defining Functions: Functions in Lua are defined using the function keyword. You can define a function with or without parameters. For example:

     function greet(name)
         print("Hello, " .. name)
     end
    
  2. Calling Functions: Once a function is defined, you can call it by using its name followed by parentheses. If the function takes parameters, you pass them inside the parentheses:

     greet("Lua")
    
  3. Anonymous Functions: Lua supports anonymous functions, which are functions without a name. These are often used for short, one-time operations or as arguments to other functions:

     local add = function(a, b)
         return a + b
     end
     print(add(3, 4))
    
  4. Returning Values: Functions can return multiple values using the return statement. This is useful for functions that need to provide more than one result:

     function divide(a, b)
         return a / b, a % b
     end
     local quotient, remainder = divide(10, 3)
    
  5. Variable Number of Arguments: Lua functions can accept a variable number of arguments using the ... syntax. This is useful for functions that need to handle an unknown number of inputs:

     function sum(...)
         local total = 0
         for _, v in ipairs({...}) do
             total = total + v
         end
         return total
     end
     print(sum(1, 2, 3, 4))
    

Here is the full program concluding the use of functions:

-- Define a function to greet a user
function greet(name)
    return "Hello, " .. name
end

-- Define a function to add two numbers
function add(a, b)
    return a + b
end

-- Define a function to calculate the factorial of a number using recursion
function factorial(n)
    if n == 0 then
        return 1
    else
        return n * factorial(n - 1)
    end
end

-- Define an anonymous function to multiply two numbers
local multiply = function(a, b)
    return a * b
end

-- Define a function to demonstrate variable number of arguments
function sum(...)
    local total = 0
    for _, v in ipairs({...}) do
        total = total + v
    end
    return total
end

-- Call the functions and print their results
print(greet("Lua")) -- Output: Hello, Lua
print("Addition: " .. add(5, 7)) -- Output: Addition: 12
print("Factorial of 5: " .. factorial(5)) -- Output: Factorial of 5: 120
print("Multiplication: " .. multiply(3, 4)) -- Output: Multiplication: 12
print("Sum: " .. sum(1, 2, 3, 4, 5)) -- Output: Sum: 15

Concluding the Guide

Lua is a powerful language with a very beginner-friendly syntax, and it is a great language for beginners to start learning. Despite not being as popular as other high-level languages, it can be used for a variety of tasks ranging from basic problem-solving to embedded programming and game development.

You can use the official Lua documentation to explore further into Lua and its different functionalities. A good place to continue learning is learning about error handling or modules and packages. If you are familiar with C, you can continue learning about how to implement the Lua C API.

Adios, and happy learning!

0
Subscribe to my newsletter

Read articles from Swastik directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Swastik
Swastik