Ты играл в Roblox, World of Warcraft, модил Garry's Mod или ковырял nginx — и даже не подозревал, что всё это время юзал Lua. Пора познакомиться нормально.
Lua — это тот самый язык, про который все говорят «ааа, это для игр», а потом оказывается, что он живёт в Redis, NGINX (OpenResty), Wireshark, Neovim и ещё в куче мест, где нужен быстрый, лёгкий встраиваемый скриптовый движок.
Весь интерпретатор Lua весит меньше 300 КБ. При этом Lua стабильно входит в топ самых быстрых скриптовых языков (LuaJIT вообще летает на уровне C в некоторых бенчмарках).

Переменные: всё просто, но есть нюанс
В Lua переменные по умолчанию глобальные. Да, прямо как в JavaScript до "use strict". И да, это ловушка.
-- Это глобальная переменная. Она видна ОТОВСЮДУ.
name = "Кодик"
-- А вот так — локальная. Используй local ВСЕГДА.
local age = 25
local is_cool = trueПравило номер один: всегда пиши local. Если забыл — переменная утекает в глобальную область видимости, и потом будешь два часа дебажить, почему counter сбрасывается в рандомных местах.
Типы данных: минимализм во всей красе
В Lua всего 8 типов. Восемь. Для сравнения — в TypeScript у тебя типов больше, чем друзей в LinkedIn.
local a = 42 -- number (и int, и float — всё number)
local b = "hello" -- string
local c = true -- boolean
local d = nil -- nil (отсутствие значения)
local e = {} -- table (массив, объект, словарь — всё в одном)
local f = print -- function (да, функции — это значения)Самое главное: table — это единственная структура данных. Массив? Table. Объект? Table. Словарь? Тоже table. HashMap? Угадай.
Таблицы: один тип, чтобы править всеми
Table в Lua — это швейцарский нож. Смотри:
-- Как массив (индексация с 1, а не с 0!)
local fruits = {"яблоко", "банан", "манго"}
print(fruits[1]) -- "яблоко" (не fruits[0]!)
-- Как словарь
local user = {
name = "Алексей",
level = "senior",
stack = {"Vue", "Nuxt", "Lua"}
}
print(user.name) -- "Алексей"
print(user["level"]) -- "senior"
-- Как и то, и другое одновременно (но лучше так не делай)
local chaos = {
"первый",
name = "хаос",
"второй",
power = 9000
}Индексация с единицы — это то, из-за чего разработчики на C, Python и JS первые 30 минут ходят с каменным лицом. Но потом привыкаешь. Обещаю.
Условия и циклы: классика жанра
Никаких фигурных скобок. Никаких elif. Просто if, elseif, then и end:
local hp = 75
if hp <= 0 then
print("Game Over")
elseif hp < 30 then
print("Критически мало HP!")
else
print("Всё нормально, живём")
endЦиклы тоже без сюрпризов:
-- Числовой for
for i = 1, 5 do
print("Итерация:", i)
end
-- While
local count = 0
while count < 3 do
print(count)
count = count + 1 -- Да, в Lua нет ++ и +=
end
-- Перебор таблицы
local heroes = {"Геральт", "Линк", "Марио"}
for index, hero in ipairs(heroes) do
print(index .. ". " .. hero)
endМомент боли: в Lua нет +=, -=, ++. Каждый раз пишешь count = count + 1 как в 2003-м. Есть предложение добавить compound-операторы, но пока — смирись.
Функции: first-class citizens
Функции в Lua — полноценные значения. Их можно сохранять в переменные, передавать как аргументы, возвращать из других функций:
-- Обычная функция
local function greet(name)
return "Привет, " .. name .. "!"
end
print(greet("Мир")) -- "Привет, Мир!"
-- Функция, которая возвращает функцию (замыкание!)
local function create_counter()
local count = 0
return function()
count = count + 1
return count
end
end
local counter = create_counter()
print(counter()) -- 1
print(counter()) -- 2
print(counter()) -- 3Lua поддерживает множественные возвращаемые значения — без всяких обёрток в массивы или объекты:
local function get_user()
return "Алексей", 25, "frontend"
end
local name, age, role = get_user()
print(name) -- "Алексей"
print(role) -- "frontend"Строки: конкатенация через ..
Забудь про + для строк. В Lua конкатенация — это ..:
local first = "Hello"
local second = "World"
print(first .. " " .. second) -- "Hello World"
-- Длина строки
print(#"Кодик") -- 10 (UTF-8 байты, не символы!)
-- string.format — как printf, только в Lua
local msg = string.format("У %s %d HP", "героя", 100)
print(msg) -- "У героя 100 HP"Важно: оператор # возвращает длину в байтах, а не в символах. Для кириллицы это ловушка — каждая буква занимает 2 байта в UTF-8.
ООП: собираем из таблиц и метатаблиц
В Lua нет классов из коробки. Но есть метатаблицы — механизм, через который можно реализовать наследование, перегрузку операторов и вообще любую объектную модель:
-- "Класс" через таблицу
local Player = {}
Player.__index = Player
function Player.new(name, hp)
local self = setmetatable({}, Player)
self.name = name
self.hp = hp
return self
end
function Player:take_damage(amount)
self.hp = self.hp - amount
if self.hp <= 0 then
print(self.name .. " повержен!")
else
print(self.name .. ": осталось " .. self.hp .. " HP")
end
end
-- Использование
local hero = Player.new("Геральт", 100)
hero:take_damage(30) -- "Геральт: осталось 70 HP"
hero:take_damage(80) -- "Геральт повержен!"Обрати внимание на двоеточие (:) — это синтаксический сахар. hero:take_damage(30) эквивалентно hero.take_damage(hero, 30). Двоеточие автоматически передаёт self.
Фишки, которые удивляют
Множественное присваивание:
local a, b = 10, 20
a, b = b, a -- swap без временной переменной!
print(a, b) -- 20, 10Тернарник через and/or:
-- В Lua нет ternary operator, но есть хак:
local status = (hp > 0) and "alive" or "dead"Varargs — переменное число аргументов:
local function sum(...)
local total = 0
for _, v in ipairs({...}) do
total = total + v
end
return total
end
print(sum(1, 2, 3, 4, 5)) -- 15Где Lua используется прямо сейчас?
Lua — это не музейный экспонат. Он работает в проде у миллиардов пользователей:
Roblox — весь игровой скриптинг на Luau (форк Lua)
Neovim — конфиги и плагины пишут на Lua, а не на VimScript
Redis — скрипты для атомарных операций
NGINX/OpenResty — высоконагруженные API-шлюзы
World of Warcraft — аддоны, которые пишут миллионы игроков
Embedded-системы — IoT-устройства, где на счету каждый килобайт
Хочешь закрепить — практикуй
Теория без практики забывается за неделю — это факт. Если хочешь реально разобраться в программировании, а не просто прочитать статью и закрыть вкладку — попробуй Кодик.
Кодик — это приложение для изучения программирования с фокусом на практику. Здесь не просто читаешь теорию — ты решаешь задачи, пишешь код и сразу видишь результат. Курсы по Python, JavaScript, HTML, CSS и другим технологиям построены так, чтобы ты мог учиться в своём темпе, с телефона или компьютера.
А ещё у нас есть Telegram-сообщество с 2000+ разработчиками, где регулярно выходят полезные посты по программированию. Это отличный способ повторять материал в удобном формате — листаешь ленту и заодно прокачиваешь знания. Подписывайся и учись вместе с нами.
Итого
Lua — это язык, который доказывает: не нужно быть сложным, чтобы быть мощным. 8 типов данных, одна структура данных, минималистичный синтаксис — и при этом он работает в геймдеве, веб-серверах, базах данных и embedded-системах.
Если ты хоть раз мечтал написать мод для любимой игры, сделать плагин для Neovim или просто хочешь выучить язык за выходные — Lua отличный выбор. Барьер входа минимальный, а возможности — вполне серьёзные.
print("Удачи в изучении Lua!")