Ctrl+C → Ctrl+V → Ctrl+C → Ctrl+V → «а почему ничего не работает?!» — знакомо? Тогда добро пожаловать.
Ты не программист, ты — копипастер 😤
Давай честно. Каждый из нас начинал примерно так:
print("Привет, Вася!")
print("Тебе 20 лет")
print("----------")
print("Привет, Маша!")
print("Тебе 22 года")
print("----------")
print("Привет, Дима!")
print("Тебе 19 лет")
print("----------")25 строк. Три раза одно и то же. И где-то плачет один рефакторинг.
А теперь представь, что таких приветствий нужно 50. Или 500. Или заказчик в пятницу вечером говорит: «А давайте вместо ---------- будет ==========?». И ты сидишь, меняешь 500 разделителей руками.
Спойлер: есть способ лучше. И он называется — функции.
Функция — это твой маленький помощник 🤖
Функция — это кусок кода, которому ты даёшь имя и можешь вызывать сколько угодно раз. Один раз написал — используешь везде. DRY-принцип в действии (Don't Repeat Yourself — не повторяйся).
Базовый синтаксис:
function имяФункции()
-- тут кодendПереписываем наш позор:
function greet(name, age)
print("Привет, " .. name .. "!")
print("Тебе " .. age .. " лет")
print("----------")
end
greet("Вася", 20)
greet("Маша", 22)
greet("Дима", 19)Было 25 строк — стало 9. А если нужно поменять разделитель? Меняем в одном месте. ОДНОМ. Красота.
Аргументы: учим функцию слушаться 🎯
Аргументы (или параметры) — это то, что ты передаёшь функции, чтобы она знала, с чем работать. Это как заказ в кафе: ты не просто говоришь «сделай еду», а уточняешь — «бургер с сыром и без лука».
function makeOrder(dish, extra, remove)
print("Заказ: " .. dish)
print("Добавить: " .. extra)
print("Убрать: " .. remove)
print("---")
end
makeOrder("Бургер", "сыр", "лук")
makeOrder("Пицца", "грибы", "анчоусы")Что тут произошло:
dish,extra,remove— параметры (переменные-слоты внутри функции)"Бургер","сыр","лук"— аргументы (конкретные значения, которые мы передаём)
Многие путают эти два слова. Технически параметры — это в определении, аргументы — это при вызове. Но если ты скажешь «аргумент» вместо «параметр» на собеседовании, мир не рухнет. Скорее всего.

Return: функция, которая не просто делает, а отдаёт 📦
Иногда функция должна не просто напечатать что-то, а вернуть результат. Для этого есть return:
function add(a, b)
return a + b
end
local result = add(5, 3)
print(result) -- 8Это как разница между поваром, который готовит и сам съедает блюдо (функция с print), и поваром, который отдаёт тебе тарелку (функция с return).
return делает функцию переиспользуемой. Результат можно сохранить в переменную, передать в другую функцию, использовать в условии:
function isAdult(age)
return age >= 18end
if isAdult(20) thenprint("Добро пожаловать!")
elseprint("Подожди пару лет 😅")
endВажный нюанс: после return функция завершается. Код после return никогда не выполнится:
function test()
return 42print("Эта строка — призрак 👻") -- никогда не выполнитсяendLua-фишка: несколько return-значений 🤯
В отличие от многих языков, Lua умеет возвращать несколько значений из функции. Это реально удобно:
function getUser()
return "Алексей", 25, "developer"end
local name, age, role = getUser()
print(name) -- Алексейprint(age) -- 25print(role) -- developerЭто как если бы курьер привёз тебе не одну посылку, а сразу три. Lua такое может, и это прекрасно.
Локальные функции: наводим порядок 🧹
В Lua функции — это обычные значения. Их можно присвоить переменной, передать как аргумент, и да — они могут быть локальными:
local function square(x)
return x * x
end
print(square(5)) -- 25Зачем local? Чтобы функция не засоряла глобальное пространство имён. В больших проектах глобальные переменные — это как разбросанные по комнате носки. Вроде работает, но найти нужный — проблема.
Правило хорошего тона: всегда делай функции локальными, если они не должны быть доступны извне.
Анонимные функции: когда имя — лишнее 🥷
Иногда функции не нужно имя. Например, если ты передаёшь её как аргумент:
local numbers = {3, 1, 4, 1, 5, 9}
table.sort(numbers, function(a, b)
return a > b -- сортировка по убываниюend)
for _, v in ipairs(numbers) doprint(v)
end-- 9, 5, 4, 3, 1, 1Анонимная функция — это как одноразовый стаканчик. Использовал и забыл. Не нужно придумывать имя, не нужно хранить в переменной.
Замыкания (closures): магия уровня «мидл+»
Замыкание — это функция, которая «помнит» переменные из своего окружения:
function createCounter()
local count = 0return function()
count = count + 1
return count
endend
local counter = createCounter()
print(counter()) -- 1print(counter()) -- 2print(counter()) -- 3Что произошло? Внутренняя функция захватила переменную count из внешней функции. И даже после того, как createCounter завершилась, count продолжает жить внутри замыкания.
Это как если бы ты ушёл из кафе, но официант всё ещё помнит твой заказ. Жутковато, но полезно.
Где это нужно? Например, для создания приватных переменных, фабрик, колбэков, и вообще — это фундамент функционального программирования.

Vararg: когда не знаешь, сколько аргументов придёт 🎲
Иногда ты не знаешь заранее, сколько аргументов передадут в функцию. Для этого в Lua есть ...:
function sum(...)
local args = {...}
local total = 0for _, v in ipairs(args) do
total = total + v
endreturn total
end
print(sum(1, 2, 3)) -- 6print(sum(10, 20, 30, 40)) -- 100... — это как шведский стол аргументов. Бери сколько хочешь.
Частые ошибки: граблеборд новичка
1. Забыл скобки при вызове
function sayHi()
print("Привет!")
end
sayHi -- ничего не произойдёт, это просто ссылка на функциюsayHi() -- вот так правильно!2. Не тот тип аргумента
function double(n)
return n * 2end
print(double("пять")) -- ошибка! строку нельзя умножить3. Забыл return
function add(a, b)
a + b -- посчитал, но никуда не вернулend
local result = add(2, 3)
print(result) -- nil 😭Эта ошибка — абсолютный чемпион. Ты думаешь, что функция что-то возвращает, а она просто молча вычисляет и выбрасывает результат в пустоту.
Рефакторим: от спагетти к шедевру 🍝 → 🏗️
Представим, что мы пишем мини-игру. Вот код «до»:
-- Игрок атакует монстраlocal playerDamage = 10 + math.random(5)
local monsterHp = 50 - playerDamage
print("Игрок нанёс " .. playerDamage .. " урона")
print("У монстра " .. monsterHp .. " HP")
-- Монстр атакует игрокаlocal monsterDamage = 5 + math.random(3)
local playerHp = 100 - monsterDamage
print("Монстр нанёс " .. monsterDamage .. " урона")
print("У игрока " .. playerHp .. " HP")А вот — «после»:
local function calcDamage(baseDamage, randomRange)
return baseDamage + math.random(randomRange)
end
local function attack(attacker, target, baseDmg, randomRange, targetHp)
local damage = calcDamage(baseDmg, randomRange)
local remainingHp = targetHp - damage
print(attacker .. " нанёс " .. damage .. " урона")
print("У " .. target .. " " .. remainingHp .. " HP")
return remainingHp
end
local monsterHp = attack("Игрок", "монстра", 10, 5, 50)
local playerHp = attack("Монстр", "игрока", 5, 3, 100)Код стал переиспользуемым, читаемым и расширяемым. Хочешь добавить критический удар? Меняешь одну функцию, а не десять мест.
📱 Хочешь прокачаться в Lua (и не только) на практике?
Теория — это хорошо, но без практики она испаряется из головы за пару дней. Знакомо, да?
Мы сделали приложение Кодик — место, где можно изучать программирование с кучей практических задач. Никакой сухой теории на 500 страниц — только понятные объяснения и задачи, которые реально прокачивают. Открыл, порешал задачки по дороге на работу — и ты уже стал чуть лучше, чем вчера.
А ещё у нас есть Telegram-канал для разработчиков 💬 — полезные посты, разборы, шпаргалки и мемы (куда без них). Больше 2000 разработчиков уже там — подписывайся, читай в удобном месте и повторяй материал без напряга. 💪
Шпаргалка: всё в одном месте 📋
Что | Как | Зачем |
|---|---|---|
Обычная функция |
| Базовый кирпичик |
С параметрами |
| Настраиваемое поведение |
С return |
| Получить результат |
Локальная |
| Не засорять глобал |
Анонимная |
| Передать как аргумент |
Замыкание | Функция внутри функции | Запомнить состояние |
Vararg |
| Неизвестное кол-во аргументов |
Итого
Функции — это не просто «штука из учебника». Это фундамент нормального кода. Без них ты пишешь простыню, с ними — строишь архитектуру.
Запомни три правила:
Если копируешь код больше двух раз — выноси в функцию
Функция должна делать одну вещь и делать её хорошо
Давай функциям понятные имена —
calcDamage, а неf1илиdoStuff
А теперь иди и отрефактори свой последний проект. Мы оба знаем, что там есть что выносить в функции. 😏
Понравилась статья? Поделись с другом, который всё ещё копипастит. Ему нужна помощь.
