Определение и вызов функций
Изучите синтаксис объявления функций, правила их вызова, а также различия между локальными и глобальными функциями.
«Определение и вызов функций» — бесплатный урок Lua Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.
Синтаксис функций
Функции в Lua определяются с помощью ключевого слова function. Тело представляет собой блок, завершаемый словом end. Функции могут быть глобальными или локальными. Вызов функции выполняется добавлением скобок с аргументами. Если аргументы не указаны, отсутствующим параметрам присваивается nil.
function sayHello(name)
print("Hello, " .. (name or "World") .. "!")
end
sayHello("Lua") -- Hello, Lua!
sayHello() -- Hello, World!
local function add(a, b)
return a + b
end
print(add(3, 4)) -- 7Возвращаемые значения
Функции возвращают значения с помощью return. В отличие от большинства языков, функции Lua могут возвращать несколько значений. Если явно ничего не вернуть, функция не возвращает значений. Лишние возвращаемые значения отбрасываются, если вызов не является последним выражением в списке.
local function minMax(t)
local lo, hi = t[1], t[1]
for i = 2, #t do
if t[i] < lo then lo = t[i] end
if t[i] > hi then hi = t[i] end
end
return lo, hi
end
local lo, hi = minMax({5,2,8,1,9})
print(lo, hi) -- 1 9Функция как значение
В Lua функции являются значениями первого класса. Вы можете хранить их в переменных, передавать как аргументы другим функциям и возвращать их. Это позволяет использовать обратные вызовы, функции высшего порядка и шаблоны функционального программирования.
local ops = {
add = function(a, b) return a + b end,
sub = function(a, b) return a - b end,
mul = function(a, b) return a * b end,
}
local function apply(op, a, b)
return op(a, b)
end
print(apply(ops.add, 10, 3)) -- 13
print(apply(ops.mul, 4, 5)) -- 20Локальные и глобальные функции
Используйте local function для вспомогательных функций, предназначенных только для модуля. Глобальные функции засоряют глобальное пространство имён и доступны отовсюду, что может привести к конфликтам имён. В большинстве случаев предпочтительны локальные функции; через таблицу модуля следует открывать только необходимое.
-- Bad: pollutes global namespace
function helper() end
-- Good: module-local
local function helper()
return "I am local"
end
-- Module export pattern
local M = {}
function M.publicFunc()
return helper() -- can call local
end
return MМетоды с синтаксисом двоеточия
Lua предоставляет синтаксическое сокращение для определения и вызова методов таблиц. obj:method(arg) эквивалентно obj.method(obj, arg). Форма с двоеточием неявно передаёт таблицу первым аргументом, который обычно называется self.
local Dog = {}
Dog.__index = Dog
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
function Dog:speak()
print(self.name .. " says: Woof!")
end
local d = Dog.new("Rex")
d:speak() -- Rex says: Woof!Шаблон необязательных параметров
В Lua нет встроенных необязательных параметров, но их можно имитировать с помощью проверок на nil. Для функций со множеством необязательных параметров передавайте одну таблицу параметров — это понятнее, чем длинный список аргументов.
local function createUser(name, opts)
opts = opts or {}
return {
name = name,
role = opts.role or "user",
active = opts.active ~= false,
score = opts.score or 0,
}
end
local u = createUser("Alice", {role="admin", score=100})
print(u.name, u.role, u.score)Хвостовые вызовы
Хвостовой вызов — это вызов функции в хвостовой позиции, то есть последнее действие перед возвратом. Lua выполняет оптимизацию хвостовых вызовов: корректный хвостовой вызов не использует дополнительную память стека. Благодаря этому возможна глубокая рекурсия без переполнения стека, если рекурсивный вызов находится в хвостовой позиции.
local function factorial(n, acc)
acc = acc or 1
if n <= 1 then return acc end
return factorial(n - 1, n * acc) -- tail call!
end
print(factorial(10)) -- 3628800
-- Can handle very large n without stack overflowФункции с немедленным вызовом
Функцию можно определить и немедленно вызвать: (function() ... end)(). Это полезно для создания локальной области видимости, однократного выполнения кода настройки или предотвращения загрязнения внешней области временными переменными.
local result = (function()
local temp = 100
local adjusted = temp * 1.5
return math.floor(adjusted)
end)()
print(result) -- 150
-- temp and adjusted not visible hereХранение функций в таблицах
Хранение функций в таблицах — идиоматичный способ проектирования модулей Lua. Таблица выполняет роль пространства имён. Функции можно определять, присваивая их полям таблицы, или использовать точечную нотацию и нотацию с двоеточием вместе с именем таблицы.
local math2 = {}
function math2.clamp(val, lo, hi)
return math.max(lo, math.min(hi, val))
end
function math2.lerp(a, b, t)
return a + (b - a) * t
end
print(math2.clamp(150, 0, 100)) -- 100
print(math2.lerp(0, 10, 0.5)) -- 5.0Замыкания как обратные вызовы
Функции высшего порядка принимают обратные вызовы. В Lua обратные вызовы — это обычные значения-функции. Замыкания особенно удобны в роли обратных вызовов, поскольку они захватывают контекст вызова и не требуют передавать дополнительные аргументы через функцию высшего порядка.
local function forEach(t, fn)
for i, v in ipairs(t) do
fn(v, i)
end
end
local sum = 0
forEach({10, 20, 30}, function(v)
sum = sum + v
end)
print(sum) -- 60
forEach({"a","b","c"}, function(v, i)
print(i, v)
end)Быстрая проверка
Каков результат выполнения: local function f() return 1, 2, 3 end; local a, b = f()?
Повторение: функции
Основные положения:
- Используйте
local function, чтобы не засорять глобальную область - Функции являются объектами первого класса: их можно сохранять в переменных и таблицах, а также передавать как аргументы
- Синтаксис с двоеточием неявно передаёт
self - Имитируйте необязательные параметры с помощью
opts or {} - Хвостовые вызовы предотвращают переполнение стека при глубокой рекурсии
- Функции, вызываемые немедленно, создают изолированные области видимости
Часто задаваемые вопросы
Урок «Определение и вызов функций» бесплатный?
Да — полный текст урока «Определение и вызов функций» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.
Чему я научусь в уроке «Определение и вызов функций»?
Изучите синтаксис объявления функций, правила их вызова, а также различия между локальными и глобальными функциями. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Lua Academy?
Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Определение и вызов функций»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Lua Academy?
Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Определение и вызов функций
- Несколько возвращаемых значений
- Переменное число аргументов и оператор ...
- Рекурсия в Lua