Complete and Quick Guide to Lua 🌑
Tags: lua, programming, tutorial, learning
Published: 2024-04-05 14:25:16

## 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.

```lua
local x = 10
y = 20

```





## 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.

```lua
local a = true
local b = false

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

```

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.

```lua
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

```





## Control Structures

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

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

```

Example of a `for` loop:
```lua
for i = 1, 10 do
  print(i)
end

```





## 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.

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

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

```
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.

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

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

```

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.

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

```





## 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:

```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()

```

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:

```lua
-- 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."

```

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.
```lua
co = coroutine.create(function ()
  print("Hello, World!")
end)

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

```
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!