0Pricing
Lua Academy · Урок

Несколько возвращаемых значений

Возвращайте и сохраняйте несколько значений, полученных в результате одного вызова функции.

«Несколько возвращаемых значений» — бесплатный урок Lua Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.

Возврат нескольких значений

В отличие от большинства языков, функции Lua могут естественным образом возвращать несколько значений из одного оператора return. Несколько значений указываются после return через запятую. Благодаря этому не нужны обёртки-объекты или выходные параметры.

local function divmod(a, b)
  return math.floor(a / b), a % b
end

local quotient, remainder = divmod(17, 5)
print(quotient, remainder)   -- 3  2

Настройка возвращаемых значений

Lua настраивает возвращаемые значения в соответствии с количеством принимающих переменных. Лишние значения отбрасываются, а отсутствующие становятся равными nil. Такая настройка выполняется, когда вызов функции находится не на последнем месте в списке выражений — в этом случае сохраняется только первое значение.

local function triple()
  return 10, 20, 30
end

local a, b, c = triple()
print(a, b, c)      -- 10  20  30

local x, y = triple()
print(x, y)         -- 10  20  (30 discarded)

local p = triple()
print(p)            -- 10  (only first when 1 var)

Настройка в средней позиции

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

local function pair()
  return 1, 2
end

-- pair() in middle: only 1 value used
local t = {pair(), pair()}
print(#t, t[1], t[2], t[3])  -- 3  1  1  2
-- first pair() gives just 1; last pair() gives 1,2

-- pair() at end: all values used
local t2 = {10, pair()}
print(#t2, t2[1], t2[2], t2[3])  -- 3  10  1  2

Скобки принудительно оставляют одно значение

Заключение вызова функции в скобки заставляет её вернуть ровно одно значение. Это полезно, когда Вам нужно только первое возвращаемое значение независимо от того, сколько значений создаёт функция.

local function coords()
  return 10, 20, 30
end

print(coords())    -- 10  20  30  (all three)
print((coords()))  -- 10  (parentheses: single value only)

local x = (coords())
print(x)           -- 10

Возвращаемые значения string.find

Многие функции стандартной библиотеки возвращают несколько значений. string.find возвращает начальную и конечную позиции совпадения (а также захваченные фрагменты). math.modf возвращает целую и дробную части. Понимание этих закономерностей помогает свободно пользоваться стандартной библиотекой.

local s = "hello world"
local start, finish = string.find(s, "world")
print(start, finish)   -- 7  11

-- math.modf: integer and fractional parts
local int, frac = math.modf(3.75)
print(int, frac)       -- 3   0.75

Сбор значений с помощью table.pack

table.pack(...) собирает все аргументы (или возвращаемые значения через ...) в таблицу. Таблица содержит поле n с общим количеством значений, включая значения nil. Это сохраняет точное количество, в отличие от #, который останавливается на первой пустой позиции.

local function getData()
  return "Alice", 30, nil, true
end

local t = table.pack(getData())
print(t.n)         -- 4
print(t[1])        -- Alice
print(t[2])        -- 30
print(t[3])        -- nil
print(t[4])        -- true

table.unpack для разворачивания

table.unpack(t, i, j) возвращает элементы таблицы как отдельные значения. Это обратная операция по отношению к table.pack. Используйте её, чтобы передать содержимое таблицы функции в качестве аргументов или развернуть значения в операторе возврата.

local args = {10, 20, 30}

local function sum3(a, b, c)
  return a + b + c
end

print(sum3(table.unpack(args)))  -- 60

-- Use in return
local function passThrough(t)
  return table.unpack(t)
end
print(passThrough({5, 6, 7}))   -- 5  6  7

Возврат в стиле обработки ошибок

Распространённое соглашение в Lua — возвращать nil, errorMessage при неудаче и результат при успехе. Вызывающий код проверяет первое возвращаемое значение: если это nil, произошла ошибка. Такой подход позволяет не использовать исключения для ожидаемых случаев неудачи.

local function openConfig(path)
  local f = io.open(path, "r")
  if not f then
    return nil, "cannot open: " .. path
  end
  local content = f:read("*a")
  f:close()
  return content
end

local data, err = openConfig("config.lua")
if not data then
  print("Error:", err)
end

Обмен значениями с несколькими возвращаемыми значениями

Несколько возвращаемых значений элегантно решают задачу обмена. Правая часть вычисляется до присваивания, поэтому a, b = b, a корректно меняет значения местами без временной переменной.

local a, b = 5, 10
print(a, b)   -- 5  10

a, b = b, a
print(a, b)   -- 10  5

-- Works for three-way rotation too
local x, y, z = 1, 2, 3
x, y, z = z, x, y
print(x, y, z)  -- 3  1  2

Соглашение о возвращаемых значениях pcall

pcall(f, ...) сама использует несколько возвращаемых значений: первое значение — логическое (true при успехе и false при ошибке), а последующие значения — это либо возвращаемые значения f, либо сообщение об ошибке. Всегда проверяйте первое возвращаемое значение, прежде чем использовать остальные.

local function risky(x)
  if x < 0 then error("negative input") end
  return math.sqrt(x)
end

local ok, result = pcall(risky, 16)
print(ok, result)   -- true  4.0

ok, result = pcall(risky, -1)
print(ok, result)   -- false  input:2: negative input

Быстрая проверка

Что выведет print((string.find("hello", "ll")))?

Повторение: несколько возвращаемых значений

Основные выводы:

  • Возвращайте несколько значений: return a, b, c
  • Лишние значения отбрасываются, а отсутствующие становятся nil
  • Вызовы в средней позиции сокращаются до 1 значения
  • (f()) принудительно оставляет ровно 1 значение
  • table.pack/table.unpack используются для динамических списков значений
  • Соглашение: при неудаче возвращайте nil, errmsg

Часто задаваемые вопросы

Урок «Несколько возвращаемых значений» бесплатный?

Да — полный текст урока «Несколько возвращаемых значений» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.

Чему я научусь в уроке «Несколько возвращаемых значений»?

Возвращайте и сохраняйте несколько значений, полученных в результате одного вызова функции. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Lua Academy?

Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Несколько возвращаемых значений»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Lua Academy?

Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

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

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