DEV Community

Nikita Dmitriev
Nikita Dmitriev

Posted on • Edited on

Complete and Quick Guide to Lua ๐ŸŒ‘

From the author

This article contains only the most basic information about Lua. What prompted me to create it was the lack of such a short guide on this language on the Internet. I only found a shortened version in the documentation, but it also seemed quite large to me. So, if thatโ€™s what youโ€™re looking for, letโ€™s start

Introduction

Lua is a powerful, lightweight scripting language that is used in a wide range of applications, from web servers to video games. It is known for its simplicity and flexibility, making it a popular choice for programmers of all skill levels.

The peculiarity of Lua is that while it supports object-oriented programming (OOP) principles, it does not have built-in classes like some other languages. Instead, Lua uses tables to simulate classes. Tables are essentially associative arrays that can contain keys and values, which can be any data type, including functions. Furthermore, arrays in Lua start with an index of 1, not 0 as in many other programming languages.

Variables

In Lua, you can declare a variable using the local keyword, followed by the variable name. If you want the variable to be global, you can omit the local keyword.

local x = 10
y = 20

Enter fullscreen mode Exit fullscreen mode

Data Types

Lua has eight basic types: nil, boolean, number, string, userdata, function, thread, and table.

Operators

Lua supports a variety of operators, including arithmetic, relational, logical, and bitwise operators.

Arithmetic operators include: + (addition), - (subtraction), * (multiplication), / (division), ^ (exponentiation), and % (modulus).

Relational operators include: == (equal to), ~= (not equal to), < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to).

Logical operators include: and (logical AND), or (logical OR), and not (logical NOT).

Bitwise operators, available from Lua 5.2 onwards, include: & (AND), | (OR), ~ (XOR), << (left shift), >> (right shift), and ~ (NOT).

It's important to note that Lua uses "short-circuit" evaluation for its logical operators, meaning it will stop evaluating as soon as the outcome is determined.

local a = true
local b = false

if a or b then
  print("At least one of the conditions is true.")
end

Enter fullscreen mode Exit fullscreen mode

In this case, Lua will stop evaluating as soon as it encounters the a variable, because it's true, and that's enough to determine the outcome of the or operation. It won't even check the value of b.

Tables

Tables in Lua are the only data structure, and they can be used to represent arrays, sets, records, graphs, trees, etc.

local numbers = {1, 2, 3}
local titles = {['luna'] = 'devops engineer', ['rudy'] = 'backend developer'}
local wtf = {1, 2, ['pithon'] = 'ml engineer'}

a = {}     -- create a table and store its reference in `a'
k = "x"
a[k] = 10        -- new entry, with key="x" and value=10
a[20] = "great"  -- new entry, with key=20 and value="great"
print(a["x"])    --> 10
k = 20
print(a[k])      --> "great"
a["x"] = a["x"] + 1     -- increments entry "x"
print(a["x"])    --> 11

Enter fullscreen mode Exit fullscreen mode

Control Structures

Lua supports the usual control structures: if statements, while loops, and for loops.

if x > y then
  print("x is greater than y")
else
  print("x is not greater than y")
end

Enter fullscreen mode Exit fullscreen mode

Example of a for loop:

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

Enter fullscreen mode Exit fullscreen mode

Iterating Over Tables

Iterating over tables in Lua is achieved through the use of loop constructs. A common method is using the pairs function with a for loop. This function returns a key-value pair for each item in the table, allowing you to access both the index and value in each iteration.

local tbl = {apple = "fruit", carrot = "vegetable", lion = "animal"}

for key, value in pairs(tbl) do
  print(key, value)
end

Enter fullscreen mode Exit fullscreen mode

In this example, the for loop will iterate over each key-value pair in the table. The pairs function is particularly useful when working with tables where the keys are not just numerical values or when the keys are not in sequence.

It's important to note that the pairs function does not guarantee any particular order when iterating over the table.

Another function, ipairs, is used specifically for tables with integer keys that are in sequence. It stops iterating once it encounters a nil value.

Arrays are just a special kind of table, and you can iterate over them using a for loop.

You can get length of an array by # as simple as of a string.

local array = {1, 2, 3, 4, 5}

for i = 1, #array do
  print(array[i])
end

Enter fullscreen mode Exit fullscreen mode

In this example, #array gives the length of the array, and array[i] accesses the i-th element in the array.

Thereโ€™s no arr[0] in lua. Every array starts with 1 index

Functions

You can declare a function in Lua using the function keyword, followed by the function name and parameters.

function add(x, y)
  return x + y
end

Enter fullscreen mode Exit fullscreen mode

Object-Oriented Programming in Lua

Lua supports object-oriented programming (OOP) principles, but it does not have built-in classes like some other languages. Instead, Lua uses tables to simulate classes. Tables are essentially associative arrays that can contain keys and values, which can be any data type, including functions.

Here is a simple example of how to implement a class in Lua:

Person = {}
Person.__index = Person

function Person.new(name, age)
  local self = setmetatable({}, Person)
  self.name = name
  self.age = age
  return self
end

function Person:greet()
  print("Hello, my name is " .. self.name .. " and I am " .. self.age .. " years old.")
end

-- To create a new instance of the class and call a method:
local john = Person.new("John", 25)
john:greet()

Enter fullscreen mode Exit fullscreen mode

In this example, Person is a table that serves as a class. The __index metamethod is set to the Person table itself, which allows instances of the class to access its methods.

The new function is a constructor that creates a new instance of the Person class. It uses setmetatable to associate the Person methods with the new instance.

The greet function is a method that all Person instances will have access to.

Lua also supports inheritance, which allows one class to inherit the properties and methods of another class. This can be done by setting the __index metamethod of the child class to the parent class. Here is an example:

-- Assuming the Person class has been defined...

Student = setmetatable({}, Person)
Student.__index = Student

function Student.new(name, age, grade)
  local self = Person.new(name, age)  -- Create a Person instance
  setmetatable(self, Student)  -- Change its metatable to Student
  self.grade = grade
  return self
end

function Student:study()
  print(self.name .. " is studying.")
end

-- To create a new instance of the Student class:
local jane = Student.new("Jane", 20, "A")
jane:study()  -- Outputs: "Jane is studying."

Enter fullscreen mode Exit fullscreen mode

In this example, Student is a subclass of Person. The new function in Student calls the new function in Person to create a Person instance, then changes its metatable to Student, effectively turning it into a Student instance.

Threads

In Lua, a thread represents an independent execution line. Lua supports multithreading by using coroutines, which are a generalization of subroutines. Coroutines in Lua are a type of collaborative multitasking where the switch from one task to another is done explicitly by a coroutine. Lua's threads are not operating system threads, but they can be used to simulate multithreading.

Threads are a type of value in Lua and they are manipulated just like any other value. You can create a thread with the coroutine.create() function, which returns a value of type thread. This function takes a single argument: a Lua function that the thread will execute.

co = coroutine.create(function ()
  print("Hello, World!")
end)

coroutine.resume(co)  -- Outputs: "Hello, World!"

Enter fullscreen mode Exit fullscreen mode

In this example, coroutine.create() creates a new coroutine with the specified function and coroutine.resume() starts or continues the execution of a coroutine.

A thread in Lua can be in one of three states: suspended, running, or dead. When you create a thread, it starts in the suspended state. Then, when you call coroutine.resume(), it goes to the running state. If the function finishes its execution or if an error occurs, the thread goes to the dead state. You can check the status of a thread with the coroutine.status() function.

Coroutines provide a lot of flexibility, as they can yield (pause) at any point in their execution and can be resumed later from where they left off. This is done using the coroutine.yield() and coroutine.resume() functions.

Note that coroutines are not a parallelism mechanism. Even though they can be used to simulate concurrency, only one coroutine runs at a time.

Conclusion

This is a very basic introduction to Lua. Lua is a powerful language that has a lot to offer, so don't hesitate to dive deeper and explore what you can do with it!

Top comments (0)