Перейти до вмісту

Lua

Матеріал з K2 ERP Wiki Ukraine — База знань з автоматизації та санкцій в Україні

SEO title: Lua — легка скриптова мова програмування для вбудовування, ігор, автоматизації та конфігурацій SEO description: Lua — Wiki-стаття про легку, швидку та вбудовувану скриптову мову програмування. Розглянуто синтаксис Lua, таблиці, функції, metatables, coroutines, LuaJIT, вбудовування в C/C++, використання в іграх, Neovim, Nginx/OpenResty, Redis, конфігураціях, автоматизації, переваги, обмеження, безпеку і хороші практики. SEO keywords: Lua, мова програмування Lua, Lua programming language, скриптова мова, embedded scripting, LuaJIT, таблиці Lua, metatables, coroutines, game scripting, Roblox Lua, Love2D, Neovim Lua, OpenResty, Nginx Lua, Redis Lua, C API, конфігурація, автоматизація, програмування Alternative to: важкі скриптові мови для embedded-сценаріїв; ручне написання конфігурацій без логіки; складні plugin-системи; статичні конфігураційні файли там, де потрібна гнучкість; C/C++ для простих сценарних задач; громіздкі runtime-середовища для ігор, плагінів і вбудованої логіки


Lua — це легка, швидка, динамічна скриптова мова програмування, створена для вбудовування в інші застосунки, автоматизації, конфігурацій, ігрової логіки, плагінів, розширень і сценаріїв, де потрібен компактний runtime.

Lua часто використовують у game development, embedded scripting, Neovim-конфігураціях, OpenResty/Nginx, Redis scripts, IoT, plugins, automation tools і застосунках, які потребують простого скриптового шару поверх основної системи.

Основна ідея: Lua — це невелика й гнучка мова, яку легко вбудувати в більшу систему, щоб користувачі або розробники могли писати сценарії, правила, конфігурації й плагіни.

Загальний опис

Lua відома простим синтаксисом, компактною реалізацією, швидким запуском, малою вагою й зручністю інтеграції з C та C++.

Lua використовується для:

  • ігрових скриптів;
  • embedded scripting;
  • конфігурацій;
  • plugin systems;
  • automation;
  • scripting у застосунках;
  • Neovim-конфігурацій;
  • OpenResty/Nginx логіки;
  • Redis Lua scripts;
  • IoT і embedded-систем;
  • прототипування;
  • навчання програмуванню;
  • простих DSL;
  • runtime-розширень.

Перевага: Lua не намагається бути великою універсальною платформою. Її сила — у простоті, компактності й легкому вбудовуванні в інші системи.

Історія Lua

Lua була створена в Бразилії як мова для конфігурацій і вбудованих сценаріїв. Назва Lua португальською означає “Місяць”.

З часом Lua стала популярною завдяки:

  • простому синтаксису;
  • малому runtime;
  • зручному C API;
  • швидкій інтеграції;
  • гнучким таблицям;
  • metatables;
  • coroutines;
  • використанню в іграх;
  • LuaJIT;
  • стабільності й переносимості.

Важливо: Lua історично створювалася як вбудовувана мова, тому її дизайн сильно орієнтований на простоту інтеграції з іншими програмами.

Для чого використовується Lua

Типові сценарії використання Lua:

  • game scripting;
  • логіка ігрових персонажів;
  • конфігурація редакторів;
  • плагіни;
  • embedded rules;
  • сценарії автоматизації;
  • швидкі runtime-налаштування;
  • lightweight DSL;
  • Nginx/OpenResty scripting;
  • Redis atomic scripts;
  • UI scripting;
  • модифікації ігор;
  • інтеграція з C/C++;
  • sandboxed scripts.

Практична роль: Lua часто є “мовою всередині програми”, а не окремою великою платформою сама по собі.

Перша програма на Lua

Простий приклад:

print("Hello, world!")

Запуск:

lua hello.lua

Lua-код виконується зверху вниз, без обов’язкової функції `main`.

Суть прикладу: Lua дозволяє дуже швидко написати й виконати простий скрипт.

Синтаксис

Lua має компактний і читабельний синтаксис.

Приклад:

local name = "Alice"
local age = 25

print("Name: " .. name)
print("Age: " .. age)

Особливості синтаксису:

  • `local` для локальних змінних;
  • `nil` для відсутності значення;
  • `..` для конкатенації рядків;
  • `then`, `do`, `end` для блоків;
  • таблиці як головна структура даних;
  • функції як значення;
  • динамічна типізація.

Перевага синтаксису: Lua легко читати й швидко вивчати, особливо для скриптових задач.

Змінні

У Lua змінні можуть бути глобальними або локальними.

Локальна змінна:

local count = 10

Глобальна змінна:

count = 10

У Lua краще використовувати `local`, щоб уникати випадкових глобальних змінних.

Критично: випадкова глобальна змінна — одна з типових помилок у Lua. Якщо значення не має бути глобальним, потрібно писати `local`.

Типи даних

Основні типи Lua:

  • `nil`;
  • `boolean`;
  • `number`;
  • `string`;
  • `function`;
  • `table`;
  • `thread`;
  • `userdata`.

Приклад:

local age = 25
local price = 19.99
local name = "Alice"
local active = true
local missing = nil

Перевірка типу:

print(type(name))
print(type(age))

Практична роль: Lua має небагато базових типів, але таблиці й функції роблять мову дуже гнучкою.

Nil

`nil` означає відсутність значення.

Приклад:

local value = nil

if value == nil then
  print("No value")
end

У таблицях присвоєння `nil` ключу фактично видаляє цей ключ:

local user = { name = "Alice", age = 25 }

user.age = nil

print(user.age)

Важливо: у Lua `nil` часто означає і “значення немає”, і “ключ відсутній у таблиці”.

Boolean

У Lua є значення `true` і `false`.

Приклад:

local active = true

if active then
  print("Active")
end

У Lua лише `false` і `nil` вважаються false-like. Число `0` і порожній рядок `""` вважаються true-like.

if 0 then
  print("0 is true in Lua")
end

Увага: на відміну від багатьох мов, у Lua число `0` не є false.

Number

Lua використовує тип `number` для чисел.

Приклад:

local a = 10
local b = 3

print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a % b)

У сучасних версіях Lua можуть відрізнятися integer і float-представлення, але для багатьох скриптових задач це приховано від користувача.

Практична роль: Lua добре підходить для простих обчислень, конфігурацій і ігрової логіки.

String

Рядки в Lua є immutable.

Приклад:

local first = "Hello"
local second = "Lua"

local message = first .. ", " .. second .. "!"

print(message)

Довгі рядки можна писати так:

local text = [[
This is a long string.
It can contain multiple lines.
]]

Практична користь: довгі рядки Lua зручні для конфігурацій, шаблонів і вбудованих текстів.

Tables

Table — головна структура даних у Lua.

Таблиця може працювати як:

  • масив;
  • словник;
  • об’єкт;
  • namespace;
  • record;
  • set;
  • module;
  • configuration object.

Приклад словника:

local user = {
  name = "Alice",
  age = 25,
  active = true
}

print(user.name)
print(user["age"])

Приклад масиву:

local numbers = {10, 20, 30}

print(numbers[1])
print(numbers[2])

Головна структура Lua: table замінює багато структур даних, які в інших мовах є окремими типами.

Індексація з 1

У Lua масиви зазвичай індексуються з 1, а не з 0.

Приклад:

local items = {"a", "b", "c"}

print(items[1]) -- a
print(items[2]) -- b
print(items[3]) -- c

Увага: індексація з 1 може бути незвичною для програмістів, які прийшли з C, JavaScript, Python, Java або Rust.

Умови

Умовна конструкція:

local age = 20

if age >= 18 then
  print("Adult")
else
  print("Minor")
end

Кілька умов:

local status = "active"

if status == "new" then
  print("New")
elseif status == "active" then
  print("Active")
else
  print("Unknown")
end

Суть умов: Lua використовує `then`, `elseif`, `else` і `end`, тому блоки читаються явно.

Цикли

Lua має кілька типів циклів.

`while`:

local count = 3

while count > 0 do
  print(count)
  count = count - 1
end

`repeat until`:

local count = 0

repeat
  count = count + 1
  print(count)
until count == 3

`for`:

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

Практична роль: цикли Lua прості й зручні для обробки таблиць, сценаріїв і повторюваної логіки.

Iteration

Для проходу по таблицях використовують `pairs` і `ipairs`.

`ipairs` для масивної частини:

local items = {"a", "b", "c"}

for index, value in ipairs(items) do
  print(index, value)
end

`pairs` для всіх key-value пар:

local user = {
  name = "Alice",
  age = 25
}

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

Важливо: `ipairs` і `pairs` мають різну поведінку. Для масивів частіше використовують `ipairs`, для словників — `pairs`.

Функції

Функція в Lua оголошується через `function`.

Приклад:

local function add(a, b)
  return a + b
end

print(add(2, 3))

Функції є значеннями:

local multiply = function(a, b)
  return a * b
end

print(multiply(2, 3))

Суть функцій у Lua: функції можна зберігати в змінних, передавати як аргументи й повертати з інших функцій.

Multiple return values

Lua підтримує повернення кількох значень із функції.

Приклад:

local function divide(a, b)
  if b == 0 then
    return nil, "division by zero"
  end

  return a / b, nil
end

local result, err = divide(10, 2)

if err then
  print("Error: " .. err)
else
  print(result)
end

Практична роль: multiple return values часто використовують для повернення результату й помилки без exceptions.

Closures

Lua підтримує closures — функції, які запам’ятовують змінні з зовнішньої області.

Приклад:

local function make_counter()
  local count = 0

  return function()
    count = count + 1
    return count
  end
end

local counter = make_counter()

print(counter())
print(counter())
print(counter())

Практична користь: closures корисні для callbacks, стану, фабрик функцій і простих об’єктних патернів.

Modules

Lua-модулі зазвичай реалізуються через таблиці.

Приклад модуля `math_utils.lua`:

local M = {}

function M.add(a, b)
  return a + b
end

function M.multiply(a, b)
  return a * b
end

return M

Використання:

local math_utils = require("math_utils")

print(math_utils.add(2, 3))

Практична роль: модулі дозволяють організовувати Lua-код і не забруднювати глобальний простір імен.

Metatables

Metatable — це спеціальна таблиця, яка змінює поведінку іншої таблиці.

Metatables дозволяють налаштовувати:

  • доступ до відсутніх полів;
  • арифметичні операції;
  • порівняння;
  • виклик як функції;
  • рядкове представлення;
  • прототипне наслідування;
  • object-like behavior.

Приклад `__index`:

local defaults = {
  role = "user"
}

local user = {
  name = "Alice"
}

setmetatable(user, {
  __index = defaults
})

print(user.name)
print(user.role)

Суть metatables: вони дозволяють будувати об’єктні, прототипні й DSL-подібні механізми поверх звичайних таблиць.

Metamethods

Metamethods — спеціальні поля metatable, які починаються з `__`.

Приклади:

  • `__index`;
  • `__newindex`;
  • `__tostring`;
  • `__call`;
  • `__add`;
  • `__sub`;
  • `__mul`;
  • `__eq`;
  • `__lt`;
  • `__le`;
  • `__len`.

Приклад `__tostring`:

local user = {
  name = "Alice"
}

setmetatable(user, {
  __tostring = function(t)
    return "User: " .. t.name
  end
})

print(user)

Увага: metatables дуже потужні, але надмірна “магія” може зробити Lua-код складним для читання й налагодження.

Об’єктно-орієнтований стиль

Lua не має класів у класичному сенсі, але дозволяє будувати object-like structures через tables і metatables.

Приклад:

local User = {}
User.__index = User

function User:new(name)
  local obj = {
    name = name
  }

  setmetatable(obj, self)
  return obj
end

function User:greet()
  return "Hello, " .. self.name
end

local user = User:new("Alice")
print(user:greet())

`:` автоматично передає `self`.

Практична роль: Lua дозволяє створювати об’єктний стиль без жорсткої вбудованої класової системи.

Двокрапка і крапка

У Lua є різниця між `.` і `:`.

Виклик через крапку:

user.greet(user)

Виклик через двокрапку:

user:greet()

Двокрапка автоматично передає об’єкт як перший аргумент `self`.

Важливо: плутанина між `.` і `:` є частою помилкою в Lua, особливо в object-like коді.

Coroutines

Coroutine — це механізм кооперативного multitasking.

Приклад:

local co = coroutine.create(function()
  print("Step 1")
  coroutine.yield()
  print("Step 2")
end)

coroutine.resume(co)
coroutine.resume(co)

Coroutines використовуються для:

  • cooperative multitasking;
  • game loops;
  • async-like logic;
  • iterators;
  • state machines;
  • scripting workflows;
  • контролю виконання сценаріїв.

Суть coroutines: виконання можна призупинити й продовжити пізніше, але керування залишається кооперативним.

Error handling

Lua має функції `error`, `pcall` і `xpcall`.

Приклад `pcall`:

local function risky()
  error("Something went wrong")
end

local ok, result = pcall(risky)

if not ok then
  print("Error: " .. result)
end

`pcall` викликає функцію в protected mode і повертає статус.

Практична роль: у Lua помилки можна або повертати як значення, або ловити через `pcall`.

Standard library

Стандартна бібліотека Lua невелика, але містить базові можливості.

Основні модулі:

  • `string`;
  • `table`;
  • `math`;
  • `io`;
  • `os`;
  • `debug`;
  • `coroutine`;
  • `utf8`;
  • `package`.

Приклад:

local text = "hello"

print(string.upper(text))
print(math.sqrt(16))

Увага: стандартна бібліотека Lua компактна. Для ширших можливостей часто потрібні зовнішні бібліотеки або API системи, в яку Lua вбудована.

Робота з файлами

Lua може читати й писати файли через `io`.

Приклад читання:

local file = io.open("data.txt", "r")

if not file then
  print("Cannot open file")
  return
end

local content = file:read("*a")
file:close()

print(content)

Приклад запису:

local file = io.open("output.txt", "w")

if file then
  file:write("Hello from Lua\n")
  file:close()
end

Важливо: під час роботи з файлами потрібно перевіряти, чи файл успішно відкритий, і закривати його після використання.

LuaJIT

LuaJIT — це високопродуктивна реалізація Lua з Just-In-Time compilation.

LuaJIT відома:

  • високою швидкістю;
  • FFI;
  • використанням у OpenResty;
  • популярністю в продуктивних runtime-сценаріях;
  • близькістю до Lua 5.1 із розширеннями.

LuaJIT часто використовують там, де потрібна швидкість Lua-коду або ефективна інтеграція з C.

Перевага LuaJIT: у багатьох сценаріях LuaJIT робить Lua дуже швидкою скриптовою мовою.

FFI

FFI у LuaJIT дозволяє викликати C-функції напряму з Lua-коду.

Приклад ідеї:

local ffi = require("ffi")

ffi.cdef[[
int printf(const char *fmt, ...);
]]

ffi.C.printf("Hello from C printf\n")

Критично: FFI дає велику силу, але також може створювати ризики безпеки, memory bugs і залежність від платформи.

Вбудовування Lua в C/C++

Одна з головних переваг Lua — просте вбудовування в C/C++ застосунки.

Lua може використовуватися як:

  • конфігураційний рушій;
  • scripting layer;
  • plugin language;
  • rule engine;
  • game logic layer;
  • automation runtime;
  • user-customizable extension system.

Приклад концепції:

C/C++ application
  → initializes Lua state
  → loads Lua script
  → exposes selected functions to Lua
  → Lua script controls configurable behavior

Практична роль: Lua дозволяє основній програмі залишатися на C/C++, а сценарії й правила змінювати без перекомпіляції всієї системи.

Game scripting

Lua дуже популярна в ігровій індустрії.

Вона використовується для:

  • логіки персонажів;
  • сценаріїв рівнів;
  • UI;
  • квестів;
  • модів;
  • поведінки NPC;
  • event scripts;
  • конфігурації gameplay;
  • швидкого iterating без повної перекомпіляції.

Lua використовується в різних ігрових рушіях, інструментах і платформах.

Перевага для ігор: Lua дозволяє дизайнерам і розробникам швидко змінювати gameplay-логіку без зміни основного engine-коду.

LÖVE

LÖVE або Love2D — фреймворк для створення 2D-ігор на Lua.

Приклад:

function love.draw()
  love.graphics.print("Hello, LÖVE!", 100, 100)
end

LÖVE підходить для:

  • 2D-ігор;
  • прототипів;
  • навчання;
  • game jams;
  • small indie games;
  • експериментів із графікою.

Практична роль: LÖVE робить Lua доступною для швидкого створення 2D-ігор і навчання game development.

Roblox Lua

На платформі Roblox використовується Lua-подібна мова Luau.

Вона застосовується для:

  • ігрової логіки;
  • взаємодії гравців;
  • UI;
  • внутрішніх систем;
  • gameplay scripts;
  • economy systems;
  • events;
  • multiplayer mechanics.

Увага: Roblox використовує Luau, який походить від Lua, але має власні особливості, типізацію й API платформи.

Neovim Lua

Neovim активно використовує Lua для конфігурації й плагінів.

Lua в Neovim застосовується для:

  • налаштувань редактора;
  • key mappings;
  • plugins;
  • LSP-конфігурацій;
  • themes;
  • automation;
  • editor scripting;
  • plugin development.

Приклад:

vim.opt.number = true
vim.opt.expandtab = true
vim.opt.shiftwidth = 2

vim.keymap.set("n", "<leader>w", ":w<CR>")

Практична роль: Lua стала основною мовою сучасної конфігурації Neovim.

OpenResty і Nginx Lua

OpenResty використовує Lua для програмованої логіки на базі Nginx.

Lua в OpenResty може використовуватися для:

  • API gateways;
  • routing;
  • rate limiting;
  • authentication;
  • request processing;
  • response transformation;
  • caching logic;
  • lightweight backend behavior;
  • high-performance web logic.

Практична роль: Lua в OpenResty дозволяє додавати гнучку логіку до Nginx без написання окремого backend-сервісу для кожного правила.

Redis Lua scripts

Redis підтримує Lua scripts для виконання логіки всередині Redis.

Lua scripts у Redis корисні для:

  • atomic operations;
  • custom commands;
  • counters;
  • locks;
  • rate limiting;
  • queue logic;
  • перевірки й оновлення кількох ключів;
  • зменшення кількості round trips.

Приклад ідеї:

local current = redis.call("GET", KEYS[1])

if current then
  return current
else
  redis.call("SET", KEYS[1], ARGV[1])
  return ARGV[1]
end

Важливо: Redis Lua scripts мають бути короткими й обережними, бо вони виконуються всередині Redis і можуть впливати на продуктивність.

Конфігурації на Lua

Lua часто використовують як мову конфігурації.

Приклад:

return {
  host = "localhost",
  port = 8080,
  debug = true,
  features = {
    cache = true,
    metrics = false
  }
}

Переваги Lua-конфігурацій:

  • можна описувати складні структури;
  • можна використовувати логіку;
  • можна створювати functions;
  • конфігурація залишається читабельною;
  • застосунок може завантажувати таблицю як дані.

Перевага: Lua-конфігурація може бути гнучкішою за JSON або INI, але простішою за повноцінну велику мову.

Sandbox

Оскільки Lua часто виконує користувацькі скрипти, важливо обмежувати доступи.

Sandbox може обмежувати:

  • файлову систему;
  • мережу;
  • `os.execute`;
  • debug library;
  • доступ до глобальних змінних;
  • небезпечні API;
  • час виконання;
  • пам’ять;
  • зовнішні модулі.

Критично: якщо Lua-скрипти пишуть користувачі або сторонні розробники, їх не можна виконувати без sandbox і контролю доступів.

Безпека Lua

Lua сама по собі компактна, але ризики залежать від того, де й як вона виконується.

Потрібно контролювати:

  • виконання сторонніх скриптів;
  • доступ до `io`;
  • доступ до `os`;
  • `debug` library;
  • FFI;
  • глобальні змінні;
  • injection у скриптах;
  • небезпечні plugins;
  • нескінченні цикли;
  • витрати пам’яті;
  • доступ до host application API.

Критично: Lua як embedded scripting language повинна отримувати лише ті можливості, які host application явно дозволяє.

Приватність даних

Lua-скрипти можуть працювати з конфігураціями, токенами, користувацькими даними або внутрішніми API.

Не варто без потреби відкривати Lua-скриптам:

  • паролі;
  • tokens;
  • API keys;
  • приватні файли;
  • персональні дані;
  • production secrets;
  • внутрішні endpoints;
  • системні команди;
  • доступ до логів;
  • необмежений доступ до host application.

Правило: Lua-скрипт має бачити лише той мінімум даних і функцій, який потрібен для конкретної задачі.

Lua і Python

Lua часто порівнюють із Python.

Критерій Lua Python
Основний фокус Embedded scripting, ігри, конфігурації, plugins Універсальна мова: web, data science, automation, AI
Runtime Дуже компактний Більший і потужніший
Екосистема Менша, але зручна для embedded Дуже велика
Вбудовування Дуже сильна сторона Можливо, але важче
Data science / AI Не основна ніша Дуже сильна екосистема

Висновок: Python кращий як універсальна мова з великою екосистемою, а Lua — як легкий embedded scripting layer.

Lua і JavaScript

Lua і JavaScript обидві є динамічними мовами, але мають різні ніші.

Критерій Lua JavaScript
Основна ніша Embedded scripting, games, configs Browser, Node.js, web ecosystem
Runtime Дуже компактний Залежить від engine
Tables / Objects Tables як універсальна структура Objects, arrays, maps
Web Не browser-native Основна мова браузера
Вбудовування Дуже зручне Можливе через engines, але складніше

Висновок: JavaScript домінує у web, а Lua часто сильніша там, де потрібна маленька вбудована мова.

Lua і C

Lua часто використовується разом із C.

Критерій Lua C
Роль Скриптова логіка Низькорівнева основа застосунку
Виконання Інтерпретатор або JIT Компіляція
Пам’ять Автоматичне керування Ручне керування
Сила Гнучкість і швидкі зміни Продуктивність і контроль
Типове поєднання Lua scripts керують поведінкою C/C++ application надає API

Практичний висновок: C/C++ часто відповідає за продуктивне ядро, а Lua — за сценарії, конфігурацію й змінну логіку.

Переваги Lua

Основні переваги Lua:

  • простий синтаксис;
  • малий runtime;
  • швидкий запуск;
  • легке вбудовування;
  • хороша інтеграція з C/C++;
  • таблиці як універсальна структура;
  • функції як first-class values;
  • closures;
  • coroutines;
  • metatables;
  • LuaJIT;
  • придатність для game scripting;
  • зручність для конфігурацій;
  • переносимість;
  • невелика складність мови.

Головна перевага: Lua дуже добре підходить як легкий, швидкий і гнучкий скриптовий шар усередині більших систем.

Обмеження Lua

Lua має обмеження.

Можливі проблеми:

  • менша екосистема, ніж у Python або JavaScript;
  • динамічна типізація;
  • випадкові глобальні змінні;
  • індексація з 1 може бути незвичною;
  • стандартна бібліотека невелика;
  • object-oriented стиль не є вбудованим класично;
  • metatables можуть ускладнювати код;
  • різні версії Lua мають несумісності;
  • LuaJIT не завжди відповідає новішим версіям Lua;
  • для великих застосунків потрібна дисципліна структури.

Помилка: використовувати Lua як заміну великій general-purpose платформі там, де потрібна широка екосистема, типізація, framework-и й production tooling.

Коли варто використовувати Lua

Lua добре підходить, коли потрібні:

  • embedded scripting;
  • конфігурації з логікою;
  • плагіни;
  • game scripting;
  • швидкі сценарії;
  • lightweight runtime;
  • C/C++ integration;
  • user-defined rules;
  • sandboxed scripts;
  • Neovim configuration;
  • Redis scripts;
  • OpenResty logic;
  • автоматизація всередині застосунку.

Практична порада: Lua варто обирати, коли головна потреба — дати системі простий і безпечний скриптовий шар.

Коли Lua може бути невдалим вибором

Lua може бути не найкращим вибором для:

  • великих backend-платформ;
  • data science;
  • machine learning;
  • enterprise web development;
  • застосунків, де потрібна сильна статична типізація;
  • великих команд без Lua-досвіду;
  • складних бізнес-систем із великою екосистемною потребою;
  • сценаріїв, де Python, JavaScript, Go або Java мають кращі бібліотеки.

Важливо: Lua найсильніша не як “мова для всього”, а як компактна вбудована мова для конкретної системи.

Хороші практики Lua

Рекомендовано:

  • використовувати `local`;
  • не забруднювати глобальний простір;
  • структурувати код через modules;
  • не зловживати metatables;
  • явно обробляти `nil`;
  • відрізняти `pairs` і `ipairs`;
  • обмежувати доступи для sandbox;
  • не відкривати небезпечні API користувацьким скриптам;
  • писати маленькі функції;
  • документувати host API;
  • перевіряти помилки через `pcall` або return values;
  • контролювати версію Lua;
  • тестувати сценарії в тому runtime, де вони виконуються.

Головне правило: хороший Lua-код має бути локальним, простим, модульним і без зайвої магії.

Типові помилки початківців

Поширені помилки:

  • забути `local`;
  • очікувати індексацію з 0;
  • плутати `.` і `:`;
  • не перевіряти `nil`;
  • неправильне використання `pairs` і `ipairs`;
  • випадково створити глобальну змінну;
  • зловживати metatables;
  • писати занадто великі scripts без modules;
  • не обмежувати sandbox;
  • припускати, що `0` є false;
  • не враховувати різницю між Lua 5.1, 5.2, 5.3, 5.4 і LuaJIT;
  • запускати сторонній код без обмежень.

Небезпека: найчастіші помилки Lua пов’язані не зі складним синтаксисом, а з глобальними змінними, nil, metatables і небезпечним виконанням сторонніх скриптів.

Приклади задач на Lua

Обробка списку

local numbers = {1, 2, 3, 4, 5}
local sum = 0

for _, value in ipairs(numbers) do
  sum = sum + value
end

print(sum)

Конфігураційна таблиця

local config = {
  host = "localhost",
  port = 8080,
  debug = true,
  features = {
    cache = true,
    metrics = false
  }
}

print(config.host)
print(config.features.cache)

Простий модуль

local M = {}

function M.greet(name)
  return "Hello, " .. name
end

return M

Простий об’єктний стиль

local Counter = {}
Counter.__index = Counter

function Counter:new()
  local obj = { value = 0 }
  setmetatable(obj, self)
  return obj
end

function Counter:increment()
  self.value = self.value + 1
end

local counter = Counter:new()
counter:increment()

print(counter.value)

Безпечний виклик через pcall

local function risky()
  error("Failed")
end

local ok, err = pcall(risky)

if not ok then
  print("Error: " .. err)
end

Підказка: у Lua важливо дивитися не лише на синтаксис, а й на те, у якому runtime або host application виконується скрипт.

Джерела

  • Офіційний сайт Lua.
  • Lua Reference Manual.
  • Programming in Lua.
  • LuaJIT documentation.
  • LuaRocks documentation.
  • LÖVE documentation.
  • Neovim Lua documentation.
  • OpenResty documentation.
  • Redis Lua scripting documentation.
  • Документація host applications, які вбудовують Lua.

Висновок

Lua — це легка, швидка й гнучка скриптова мова програмування, яка особливо добре підходить для вбудовування в інші застосунки, ігрових сценаріїв, конфігурацій, плагінів, автоматизації, Neovim, OpenResty, Redis scripts і runtime-розширень.

Її головні сильні сторони — простота, компактність, tables, functions, closures, metatables, coroutines, LuaJIT і зручна інтеграція з C/C++. Водночас Lua має обмеження: динамічна типізація, випадкові глобальні змінні, невелика стандартна бібліотека, різні версії runtime і потреба в sandbox для сторонніх скриптів.

Головна думка: Lua — це мова для легкого скриптингу й вбудовування. Вона найкраще працює тоді, коли основна система надає API, а Lua описує змінну логіку, правила, конфігурації або плагіни.

Див. також

Тематичні мітки