{}const=>[]async()letfn</>var
LuaРазработкаОсновы

Функции в Lua: как собрать код в “кирпичики” и перестать копипастить 🧩

Разбираемся с функциями в Lua — от базового синтаксиса до замыканий и vararg. Учимся писать чистый, переиспользуемый код вместо бесконечного копипаста. С примерами, мемами и граблями новичков.

К

Кодик

Автор

7 мин чтения

Ctrl+C → Ctrl+V → Ctrl+C → Ctrl+V → «а почему ничего не работает?!» — знакомо? Тогда добро пожаловать.

Ты не программист, ты — копипастер 😤

Давай честно. Каждый из нас начинал примерно так:

print("Привет, Вася!")
print("Тебе 20 лет")
print("----------")

print("Привет, Маша!")
print("Тебе 22 года")
print("----------")

print("Привет, Дима!")
print("Тебе 19 лет")
print("----------")

25 строк. Три раза одно и то же. И где-то плачет один рефакторинг.

А теперь представь, что таких приветствий нужно 50. Или 500. Или заказчик в пятницу вечером говорит: «А давайте вместо ---------- будет ==========. И ты сидишь, меняешь 500 разделителей руками.

Спойлер: есть способ лучше. И он называется — функции.

🔥 100 000+ учеников уже с нами

Устал читать теорию?
Пора кодить!

Кодик — приложение, где ты учишься программировать через практику. AI-наставник, интерактивные уроки, реальные проекты.

🤖 AI 24/7
🎓 Сертификаты
💰 Бесплатно
🚀 Начать учиться
Присоединились сегодня

Функция — это твой маленький помощник 🤖

Функция — это кусок кода, которому ты даёшь имя и можешь вызывать сколько угодно раз. Один раз написал — используешь везде. 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("Эта строка — призрак 👻") -- никогда не выполнитсяend

Lua-фишка: несколько 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 разработчиков уже там — подписывайся, читай в удобном месте и повторяй материал без напряга. 💪

Шпаргалка: всё в одном месте 📋

Что

Как

Зачем

Обычная функция

function name() end

Базовый кирпичик

С параметрами

function name(a, b) end

Настраиваемое поведение

С return

return value

Получить результат

Локальная

local function name() end

Не засорять глобал

Анонимная

function(a) return a end

Передать как аргумент

Замыкание

Функция внутри функции

Запомнить состояние

Vararg

function name(...) end

Неизвестное кол-во аргументов

Итого

Функции — это не просто «штука из учебника». Это фундамент нормального кода. Без них ты пишешь простыню, с ними — строишь архитектуру.

Запомни три правила:

  1. Если копируешь код больше двух раз — выноси в функцию

  2. Функция должна делать одну вещь и делать её хорошо

  3. Давай функциям понятные именаcalcDamage, а не f1 или doStuff

А теперь иди и отрефактори свой последний проект. Мы оба знаем, что там есть что выносить в функции. 😏

Понравилась статья? Поделись с другом, который всё ещё копипастит. Ему нужна помощь.

🎯Хватит откладывать

Понравилась статья?
Пора применять на практике!

В Кодик ты не просто читаешь — ты сразу пишешь код. Теория + практика = реальный скилл.

Мгновенная практика
🧠AI объяснит код
🏆Сертификат

Без регистрации • Без карты