Lua is a lightweight, efficient, and versatile scripting language known for its simplicity and extensibility. It was created by Roberto Ierusalimschy, Waldemar Celes, and Luiz Henrique de Figueiredo at the Pontifical Catholic University of Rio de Janeiro in Brazil in 1993. The name "Lua" translates to "moon" in Portuguese, reflecting the language's intention to be a small and beautiful extension to existing systems. Lua is often used as an embedded scripting language in various applications and has gained popularity in the game development industry for its ease of integration and speed. Its clean and intuitive syntax, along with a powerful set of features, makes Lua a preferred choice for developers seeking a fast and efficient language for their projects.
-- This is a single-line comment
--[[
This is a multi-line comment
that spans multiple lines
]]--
Lua is dynamically typed and uses the following data types:
-- Variables are global by default
local age = 25
-- Basic data types
local name = "John"
local isStudent = true
local score = 98.5
-- nil represents absence of value
local result = nil
local grade = 85
if grade >= 90 then
print("A")
elseif grade >= 80 then
print("B")
else
print("C")
end
local count = 1
while count <= 5 do
print(count)
count = count + 1
end
for i = 1, 5, 2 do
print(i)
end
-- Function definition
function add(a, b)
return a + b
end
-- Function with multiple return values
function divideAndRemainder(a, b)
return a // b, a % b
end
-- Function with anonymous function (lambda)
local multiply = function(a, b)
return a * b
end
Tables are Lua's primary data structure, which can be used as arrays, dictionaries, or objects.
-- Empty table
local emptyTable = {}
-- Table with array-like values
local colors = {"red", "green", "blue"}
-- Table with key-value pairs
local person = {
name = "Alice",
age = 30,
isStudent = true
}
print(colors[1]) -- Output: "red"
print(person.name) -- Output: "Alice"
Metatables allow you to define custom behavior for tables and implement operator overloading.
local t1 = {x = 10, y = 20}
local t2 = {x = 5, y = 15}
-- Define the add metamethod
local addMetamethod = function(t1, t2)
return {x = t1.x + t2.x, y = t1.y + t2.y}
end
local mt = {
__add = addMetamethod
}
setmetatable(t1, mt)
local result = t1 + t2
print(result.x, result.y) -- Output: 15 35
Lua supports closures, which are functions that can access variables from their containing function.
function outerFunction(x)
local y = 10
-- Closure function
local innerFunction = function(z)
return x + y + z
end
return innerFunction
end
local closureFunction = outerFunction(5)
print(closureFunction(3)) -- Output: 18
Modules help organize code and promote code reusability.
local mymodule = {}
function mymodule.add(a, b)
return a + b
end
return mymodule
local mymodule = require("mymodule")
local result = mymodule.add(3, 5)
print(result) -- Output: 8
local success, result = pcall(function()
-- Code that may raise an error
error("Something went wrong!")
end)
if success then
print("No error occurred.")
else
print("Error:", result)
end
-- Print to console
print("Hello, Lua!")
-- Read input from user
io.write("Enter your name: ")
local name = io.read()
print("Hello, " .. name .. "!")
Although Lua is not a fully object-oriented language, you can implement OOP concepts using tables and metatables.
-- Define a class
local Person = {
name = "",
age = 0,
}
-- Constructor
function Person:new(name, age)
local newObj = { name = name, age = age }
self.__index = self
return setmetatable(newObj, self)
end
-- Methods
function Person:sayHello()
print("Hello, my name is " .. self.name)
end
-- Create an instance
local person1 = Person:new("Alice", 30)
person1:sayHello() -- Output: "Hello, my name is Alice"
Lua supports lightweight concurrency through coroutines.
-- Define a coroutine
local myCoroutine = coroutine.create(function()
print("Coroutine started.")
coroutine.yield()
print("Coroutine resumed.")
end)
-- Resume the coroutine
coroutine.resume(myCoroutine) -- Output: "Coroutine started."
-- Resume the coroutine after yielding
coroutine.resume(myCoroutine) -- Output: "Coroutine resumed."
-- Write to a file
local file = io.open("data.txt", "w")
file:write("Hello, Lua!")
file:close()
-- Read from a file
file = io.open("data.txt", "r")
local content = file:read("*a")
file:close()
print(content) -- Output: "Hello, Lua!"
local function divide(a, b)
assert(b ~= 0, "Division by zero is not allowed.")
return a / b
end
local success, result = pcall(divide, 10, 0)
if success then
print("Result:", result)
else
print("Error:", result)
end
Lua's standard library provides various useful functions for string manipulation, math operations, table manipulation, and more.
local text = "Lua is awesome!"
print(string.upper(text)) -- Output: "LUA IS AWESOME!"
print(string.len(text)) -- Output: 15
print(string.sub(text, 1, 3)) -- Output: "Lua"
print(math.sqrt(16)) -- Output: 4
print(math.random(1, 10)) -- Output: Random number between 1 and 10
local colors = {"red", "green", "blue"}
-- Insert elements
table.insert(colors, "
yellow")
-- Remove elements
table.remove(colors, 2)
-- Iterate over table
for i, color in ipairs(colors) do
print(i, color)
end
You can customize the Lua environment to control available functions and limit access to certain features.
-- Custom environment
local myEnv = {
print = function(...)
print("This is a custom print function.")
end
}
setmetatable(myEnv, {__index = _G})
-- Execute Lua code in the custom environment
local code = [[
print("Hello, Lua!")
print("This is a test.")
]]
local chunk = load(code, "test.lua", "t", myEnv)
chunk() -- Output: "This is a custom print function."
Metatables in Lua allow you to define custom behaviors for tables, including operator overloading.
-- Define a metatable
local myMetatable = {
__add = function(a, b)
return { x = a.x + b.x, y = a.y + b.y }
end,
__tostring = function(self)
return "(" .. self.x .. ", " .. self.y .. ")"
end
}
-- Create tables with the metatable
local t1 = { x = 10, y = 20 }
local t2 = { x = 5, y = 15 }
setmetatable(t1, myMetatable)
setmetatable(t2, myMetatable)
local result = t1 + t2
print(result) -- Output: (15, 35)
Lua's module system allows you to create reusable libraries and split code across multiple files.
-- Define a module table
local mymodule = {}
-- Private function
local function privateFunction()
print("This is a private function.")
end
-- Public function
function mymodule.publicFunction()
print("This is a public function.")
end
-- Return the module table
return mymodule
-- Load the module
local mymodule = require("mymodule")
mymodule.publicFunction() -- Output: "This is a public function."
Luarocks is a package manager for Lua that simplifies installing and managing external Lua modules.
# Install a Lua module
luarocks install luasocket
# List installed modules
luarocks list
# Remove a module
luarocks remove luasocket
Lua's debug
library provides functions to access and manipulate the Lua debugging information.
-- Stack trace
function myFunction()
local level = 1
while true do
local info = debug.getinfo(level, "nSl")
if not info then break end
print("Function: " .. info.name .. ", Line: " .. info.currentline .. ", Source: " .. info.source)
level = level + 1
end
end
myFunction()
Lua has automatic garbage collection to manage memory.
-- Force garbage collection
collectgarbage()
Lua provides several basic libraries that you can use in your scripts.
-- Get the current time
local currentTime = os.time()
print(currentTime)
-- Convert time to date
local date = os.date("*t", currentTime)
print(date.year, date.month, date.day)
-- Read a file
local file = io.open("data.txt", "r")
local content = file:read("*a")
file:close()
print(content)
-- Write to a file
file = io.open("output.txt", "w")
file:write("Lua is awesome!")
file:close()
print(math.sqrt(16)) -- Output: 4
print(math.random(1, 10)) -- Output: Random number between 1 and 10
local text = "Lua is awesome!"
print(string.upper(text)) -- Output: "LUA IS AWESOME!"
print(string.len(text)) -- Output: 15
print(string.sub(text, 1, 3)) -- Output: "Lua"
LuaJIT is a Just-In-Time Compiler for Lua, providing significant performance improvements.
-- Install LuaJIT (on platforms where it's supported)
# Linux - Ubuntu
sudo apt-get install luajit
-- Use LuaJIT as the interpreter
luajit script.lua
Lua can be extended with C/C++ to improve performance and integrate with existing C/C++ codebases.
// myextension.c
#include <lua.h>
#include <lauxlib.h>
// C function to add two numbers
static int add(lua_State* L) {
int a = luaL_checknumber(L, 1);
int b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1;
}
// List of functions to expose to Lua
static const luaL_Reg mylib[] = {
{"add", add},
{NULL, NULL} // Sentinel
};
int luaopen_myextension(lua_State* L) {
luaL_newlib(L, mylib);
return 1;
}
# Linux - Your Lua libs may be located in a different place depending on the Linux distribution.
gcc -shared -o myextension.so -I/usr/include/lua5.1 myextension.c
# macOS
gcc -shared -o myextension.so -I/usr/local/include/lua5.1 myextension.c
-- main.lua
local myextension = require("myextension")
local result = myextension.add(3, 5)
print(result) -- Output: 8
Light userdata allows you to store C pointers in Lua without being subject to garbage collection.
// myuserdata.c
#include <lua.h>
#include <lauxlib.h>
// C struct
typedef struct {
int x;
int y;
} Point;
// Create a new Point and push it as light userdata
static int newPoint(lua_State* L) {
Point* point = (Point*)lua_newuserdata(L, sizeof(Point));
point->x = luaL_checknumber(L, 1);
point->y = luaL_checknumber(L, 2);
luaL_getmetatable(L, "point_metatable");
lua_setmetatable(L, -2);
return 1;
}
// Metamethod for garbage collection
static int gcPoint(lua_State* L) {
Point* point = (Point*)lua_touserdata(L, 1);
// Add cleanup code here if necessary
return 0;
}
// List of functions to expose to Lua
static const luaL
_Reg mylib[] = {
{"newPoint", newPoint},
{NULL, NULL} // Sentinel
};
int luaopen_myuserdata(lua_State* L) {
luaL_newmetatable(L, "point_metatable");
lua_pushstring(L, "__gc");
lua_pushcfunction(L, gcPoint);
lua_settable(L, -3);
luaL_newlib(L, mylib);
return 1;
}
# Linux - Your Lua libs may be located in a different place depending on the Linux distribution.
gcc -shared -o myuserdata.so -I/usr/include/lua5.1 myuserdata.c
# macOS
gcc -shared -o myuserdata.so -I/usr/local/include/lua5.1 myuserdata.c
-- main.lua
local myuserdata = require("myuserdata")
local p = myuserdata.newPoint(10, 20)
print(p) -- Output: userdata: 0x...
-- Accessing C struct fields
print(p.x, p.y) -- Output: 10 20
Lua can be embedded in C/C++ applications to provide scripting capabilities.
// main.c
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main() {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
// Load and execute a Lua script
luaL_dofile(L, "script.lua");
// Close Lua state
lua_close(L);
return 0;
}
// main.cpp
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
int main() {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
// Load and execute a Lua script
luaL_dofile(L, "script.lua");
// Close Lua state
lua_close(L);
return 0;
}
Lua can be used in mobile app development, especially with game engines like Corona SDK and Defold.
-- Corona SDK example
local background = display.newRect(display.contentCenterX, display.contentCenterY, display.actualContentWidth, display.actualContentHeight)
background:setFillColor(0.5, 0.5, 0.5)
local text = display.newText("Hello, Corona!", display.contentCenterX, display.contentCenterY, native.systemFont, 24)
text:setFillColor(1, 1, 1)
Lua can be used in web development with frameworks like Lapis and Sailor.
-- Lapis example
local lapis = require("lapis")
local app = lapis.Application()
app:get("/", function(self)
return "Hello, Lapis!"
end)
app:run()
Lua is commonly used as a scripting language for game engines like Unity and Unreal Engine.
-- Unity C# with embedded Lua example
using System.Collections;
using UnityEngine;
using LuaInterface;
public class LuaScript : MonoBehaviour {
private Lua lua;
private void Start() {
lua = new Lua();
lua.DoString("print('Hello from Lua!')");
}
private void OnDestroy() {
lua.Dispose();
}
}
This is great!