0Pricing
Lua Academy · Урок

Определение и вызов функций

Изучите синтаксис объявления функций, правила их вызова, а также различия между локальными и глобальными функциями.

«Определение и вызов функций» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Определение и вызов функций
  2. Несколько возвращаемых значений
  3. Переменное число аргументов и оператор ...
  4. Рекурсия в Lua
← Назад к Lua Academy