Lua, known for its speed, efficiency, and versatility, has a rich history and is widely used across various industries. It incorporates data-description from Simple Object Language (SOL) while adding traditional programming control flow syntax from Modula, a descendant of Pascal. "Lua" means "Moon" in Portuguese, a play on "SOL" meaning "Sun". Lua is active and continuously being evolved becoming more of a powerhouse in scripting language.
Lua's speed and lightweight design make it a preferred choice for applications ranging from game development to embedded systems. Its adaptability across different programming paradigms, including procedural, object-oriented, and functional programming, provides developers with flexibility in crafting solutions tailored to their needs.
Lua's dynamic typing and excellent embeddability make it a standout choice for customization and extensibility. With automatic memory management through incremental garbage collection, Lua ensures efficient memory usage without manual intervention.
As you explore the features, comparisons, and examples on this page, you'll discover the breadth of Lua's capabilities and its significance in the world of scripting languages.
Lua was created in 1993 by members of Pontifical Catholic University of Rio de Janeiro, Roberto Ierusalimschy, Luiz Henrique de Figueiredo, and Waldemar Celes who could not obtain customized software from outside of Brazil. Lua was created with the goal of being a powerful yet lightweight scripting language. Over the years, it has gained popularity in various domains, including game development, embedded systems, and scripting for applications. Lua's simplicity and efficiency have contributed to its enduring success and widespread adoption.
Lua's design principles prioritize ease of integration, making it a go-to choice for embedding in applications and platforms with resource constraints. Its journey from inception to becoming one of the fastest scripting languages showcases the commitment of its developers to deliver a versatile and efficient tool for programmers.
Lua is extensively used in various industries, including game development, where its speed and flexibility shine. Its embeddable nature makes it a popular choice for scripting within game engines, allowing developers to enhance and customize game behavior. Some notable games that where Lua has been apart of are games such as Roblox, Garry's Mod, and World of Warcraft. There are other applications such as the web server Nginx, Wireshark, and Adobe Lightroom for similar reasons.
Lua's capabilities extend beyond traditional shell scripting languages. Here's a comparison between Lua and a typical shell scripting language:
Feature | Lua | Shell Scripting |
---|---|---|
Performance | High | Varies, generally lower than Lua |
Programming Paradigms | Procedural, Object-Oriented, Functional | Primarily Procedural |
Typing | Dynamic | Dynamic/Weak |
Embeddability | Excellent | Less Common |
Memory Management | Automatic Garbage Collection | Manual |
Lua and Python are both versatile scripting languages, but they have distinct characteristics. Here's a comparison between Lua and Python:
Feature | Lua | Python |
---|---|---|
Performance | High | Moderate to High |
Programming Paradigms | Procedural, Object-Oriented, Functional | Procedural, Object-Oriented, Functional |
Typing | Dynamic | Dynamic/Strong |
Embeddability | Excellent | Embeddable, widely used in various applications |
Memory Management | Automatic Garbage Collection | Automatic Garbage Collection |
Lua's syntax is similar to other scripting languages, but it has some unique characteristics. Here's a comparison of syntax between Lua and other scripting languages:
Language | Code |
---|---|
Lua |
-- global
|
Shell (Bash) |
# global
|
Python |
# global - outside a function
|
Operators |
-- Lua
|
If/Else/Else If |
-- Lua
|
For/While |
-- Lua
|
Functions |
-- Lua
|
Reading input |
-- Lua
|
Lua is implemented in pure ANSI C and compiles unmodified in all platforms that have an ANSI C compiler. You only need the Lua library and the Lua header files to compile Lua programs. There are two main ways to install Lua on your machine.
Lua can be installed via the Linux Terminal. The commands to download and install Lua will depend on your Linux distribution. For example:
Debian/Ubuntu
Open a terminal window and run the following commands:
$ sudo apt update
$ sudo apt-get install lua
This will display a list of all different packages offers. The user must explicitly select one version to install. For the latest version run the following commands:
$ sudo apt update
$ sudo apt-get install lua5.4
If successfully installed. The Lua interpreter can be used directly in the terminal. Run the following commands to use the Lua interpreter:
$ lua
Lua 5.4.6 Copyright (C) 1994-2020 Lua.org, PUC-Rio
>
Lua is a free software distributed in source code form. If you want to mess with the complier or build it yourself, you can build it from source. To build Lua, you need the library and the header files. You can download the latest release from the Lua website.
curl -R -O http://www.lua.org/ftp/lua-5.4.6.tar.gz
tar zxf lua-5.4.6.tar.gz
cd lua-5.4.6
make all test
Note: If you don't have curl, try wget. If you don't have tar, try gunzip and tar. If you don't have make, just use the files src/lua and src/luac.
Lua's community is very active and friendly. You can get help from the Lua community in many ways:
The first program that every programmer writes is the Hello World program. Lua is no different. Here is the Hello World program in Lua:
print("Hello World")
To run the program, save it in a file called hello.lua and run it with the command lua hello.lua. You should see the following output:
Hello World
If you are using the stand-alone Lua interpreter, all you have to do to run your first program is to call the interpreter (usually named lua) with the name of the text file that contains your program. If you are using the Lua interpreter as a shell, you can type your program and then press Ctrl+D (on Unix) or Ctrl+Z (on Windows) to signal the end of your program. The Lua interpreter will then run your program.
prompt> lua hello.lua
The factorial of a number is the product of all the integers from 1 to that number. For example, the factorial of 6 is 1*2*3*4*5*6 = 720. Factorial is normally used in Combinations and Permutations (mathematics).
Here is a simple program to compute the factorial of a number:
function factorial(n)
if n == 0 then
return 1
else
return n * factorial(n-1)
end
end
print(factorial(6))
To run the program, save it in a file called factorial.lua and run it with the command lua factorial.lua. You should see the following output:
720
Here is a simple program to list all the files in a directory:
for file in io.popen('ls -a'):lines() do
print(file)
end
To run the program, save it in a file called listfiles.lua and run it with the command lua listfiles.lua. You should see the following output:
.
..
assets
index.html
script.js
styles.css
Lua has NO classes!!!
-- Person "class"
Person = {}
function Person:new(name, age)
local obj = { name = name, age = age }
setmetatable(obj, Person)
Person.__index = Person
return obj
end
function Person:getName()
return self.name
end
function Person:getAge()
return self.age
end
function Person:toString()
return self:getName() .. " " .. self:getAge()
end
-- Student "class" (inherits from Person)
Student = setmetatable({}, { __index = Person })
function Student:new(name, age, major)
local obj = Person:new(name, age)
setmetatable(obj, self)
self.__index = self
obj.major = major
return obj
end
function Student:getMajor()
return self.major
end
function Student:toString()
return Person.toString(self) .. " " .. self:getMajor()
end
-- Main program
local pp = Person:new("Ann", 21)
local ss = Student:new("Bob", 22, "cs")
local ps = Student:new("Carla", 23, "math")
print("pp:getName() => " .. pp:getName())
print("ss:getName() => " .. ss:getName())
print("pp:toString() => " .. pp:toString())
print("ss:toString() => " .. ss:toString())
print("ps:getName() => " .. ps:getName())
print("ps:toString() => " .. ps:toString())
This program is a demonstration of coroutines in Lua. While there are libraries for Lua which allow coroutines to sleep, "vanilla" Lua does not have this so there is a bit of playing with the coroutines' ability to yield to accomplish the same effect as sleeping.
function sleep(q, i)
local t0 = os.clock()
while os.clock() - t0 <= i do coroutine.yield(false) end
table.insert(q,i)
couroutine.yield(true)
end
seq = {5,6,1,8,3,7}
coroutines = {}
q = {}
-- create the coroutines
for i = 1, #seq do
table.insert(coroutines, coroutine.create(sleep))
end
-- start the coroutines for the first time
for i = 1, #coroutines do
coroutine.resume(coroutines[i], q, seq[i])
end
-- resume the coroutines repeatedly, remove from table when complete
-- (fake multithreading)
while #coroutines > 0 do
rem = {}
for i = 1, #coroutines do
status, done = coroutine.resume(coroutines[i])
if done then
table.insert(rem,i)
end
end
for i = 1, #rem do
table.remove(coroutines,rem[i])
end
end
--print them
for i = 1, #q do
io.write(q[i], " ")
end
print()
To run the program, save it in a file called sleep.lua and run it with the command lua sleep.lua. You should see the following output (after eight seconds):
1 3 5 6 7 8
numWins = 0
numLoss = 0
function generate(min, max)
return math.random(min, max)
end
function play()
local min = 1
local max = 10
local userNum = nil
local computerNum = nil
local playerTurn = true
local ongoing = true
local playerWin = false
print("")
print("Computer and player take turns guessing each other's numbers.")
print("Numbers are between 1 and 10. First to guess wins!")
while(ongoing) do
if playerTurn then
computerNum = generate(min, max)
playerTurn = false
print("Your guess:")
userNum = tonumber(io.read())
while(userNum == nil) do
print("Invalid input. Please enter a number.")
userNum = tonumber(io.read())
end
print("The number was", computerNum)
print("")
if userNum == computerNum then
playerWin = true
ongoing = false
end
else
computerNum = generate(min, max)
playerTurn = true
print("Computer guess created. What was your number?")
userNum = tonumber(io.read())
while(userNum == nil) do
print("Invalid input. Please enter a number.")
userNum = tonumber(io.read())
end
print("The guess was", computerNum)
print("")
if userNum == computerNum then
playerWin = false;
ongoing = false;
end
end
end
if playerWin then
print("Your guess was correct! You win!")
numWins = numWins + 1
else
print("Computer guessed correctly! Computer wins.")
numLoss = numLoss + 1
end
end
function displaymenu()
print("")
print("---------- MENU ----------")
print("p - play game")
print("d - display wins")
print("q - quit")
print("--------------------------")
print("")
end
function menu()
local userChoice = "a"
while(userChoice ~= "q" or "Q") do
displaymenu()
print("")
print("What do you want to do?")
userChoice = io.read()
-- lua has no switch statements
if userChoice == "p" then
play()
elseif userChoice == "q" then
print("")
break
elseif userChoice == "d" then
print("")
print("Number of wins:", numWins)
print("Number of losses:", numLoss)
print("")
else
print("Invalid Input.")
print("")
end
end
end
menu()
The code defines a number guessing game where the player takes turns guessing a random number generated by the computer. The player and the computer alternate turns, and the first to correctly guess the opponent's number wins. The game is menu-driven, allowing the player to play a round, display the number of wins and losses, or quit the game.
The provided Lua program consists of multiple files representing a basic banking system. Each file defines different
components of the system, including accounts, a bank, customers, and specific types of accounts such as checking and
savings accounts.
AbstractAccount.lua: Defines the abstract structure for an account, including methods for deposit,
withdrawal, balance retrieval, interest accrual, and conversion to a string representation.
Bank.lua: Implements a simple bank that can manage accounts, accrue interest on all accounts, and
convert the entire bank's information to a string representation.
CheckingAccount.lua: Extends the abstract account to represent a checking account, inheriting the
methods defined in AbstractAccount.lua.
Customer.lua: Defines a customer with a name and a method to convert the customer information to a
string.
SavingAccount.lua: Extends the abstract account to represent a savings account, inheriting methods
from AbstractAccount.lua and adding interest accrual functionality.
The structure allows for creating bank accounts, managing them in a bank, and performing basic banking operations
such as deposit, withdrawal, and interest accrual.
To use this program effectively, instantiate customer objects, create specific account types, add them to the bank,
and perform operations as needed.
Customer = {}
function Customer:new(name)
O = {} -- create object if user does not provide one
setmetatable(O, self)
self.__index = self
O.name = name
return O
end
function Customer:toString()
return self.name
end
require "Customer"
AbstractAccount = {}
function AbstractAccount:new(number, customer, balance)
NewAccount = {}
(NewAccount, self)
self.__index = self
NewAccount.number = number
NewAccount.customer = customer
NewAccount.balance = balance
return NewAccount
end
function AbstractAccount:deposit(amount)
self.balance = self.balance + amount
end
function AbstractAccount:withdraw(amount)
self.balance = self.balance - amount
end
function AbstractAccount:getBalance()
return self.balance
end
function AbstractAccount:accrue(rate) end
function AbstractAccount:toString()
return self.number .. ":" .. self.customer:toString() .. ":" .. self.balance
end
require "AbstractAccount"
CheckingAccount = AbstractAccount:new()
function CheckingAccount:new(number, customer, balance)
NewChkAcc = AbstractAccount:new(number, customer, balance)
setmetatable(NewChkAcc, self)
self.__index = self
return NewChkAcc
end
require "AbstractAccount"
SavingAccount = AbstractAccount:new{interest = 0.0}
function SavingAccount:new(number, customer, balance)
NewSavAcc = AbstractAccount:new(number, customer, balance)
setmetatable(NewSavAcc, self)
self.__index = self
NewSavAcc.interest = 0.0
return NewSavAcc
end
function SavingAccount:accrue(rate)
self.interest = self.interest + (self.balance * rate)
self.balance = self.balance + (self.balance * rate)
end
require "CheckingAccount"
require "SavingAccount"
Bank = {accounts = {}}
function Bank:add(account)
self.accounts[account.number] = account
end
function Bank:accrue(rate)
for _, acc in pairs(self.accounts) do
acc:accrue(rate)
end
end
function Bank:toString()
local retString = ""
for _, acc in pairs(self.accounts) do
retString = retString .. acc:toString() .. "\n"
end
return retString
end
This is an output example of the Bank program:
>require "Bank"
true
>c=Customer:new("Tom")
> chkAcc = CheckingAccount:new("101", c, 100.0)
> savAcc = SavingAccount:new("102", c, 200.0)
> Bank:add(chkAcc)
> Bank:add(savAcc)
> print(Bank:toString())
102:Tom:200.0
101:Tom:100.0
> Bank:accrue(0.02)
> print(Bank:toString())
102:Tom:204.0
101:Tom:102.0