0Pricing
Lua Academy · Урок

Композиция функций

Объединяйте преобразования в цепочку.

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

Что такое композиция?

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

В математике это записывается как f(g(x)). Композиция позволяет строить большие преобразования из небольших функций, каждая из которых решает одну задачу.

Композиция двух функций

Вспомогательная функция compose принимает две функции и возвращает новую. При её вызове сначала выполняется g, а затем результат передаётся в f.

Порядок важен: сначала выполняется внутренняя функция, а внешняя функция работает с её результатом.

local function compose(f, g)
  return function(x)
    return f(g(x))
  end
end

local function inc(n) return n + 1 end
local function dbl(n) return n * 2 end

local incThenDouble = compose(dbl, inc)
print(incThenDouble(3))

Порядок важен

Перестановка аргументов меняет результат. compose(f, g) означает: сначала применить g, затем f.

Пример ниже показывает, что удвоение, а затем увеличение на единицу дают другой результат, чем увеличение на единицу, а затем удвоение.

local function compose(f, g) return function(x) return f(g(x)) end end
local function inc(n) return n + 1 end
local function dbl(n) return n * 2 end

print(compose(dbl, inc)(3))
print(compose(inc, dbl)(3))

Композиция функций для строк

Композиция работает с любыми функциями от одного аргумента, в том числе с функциями преобразования строк. Объединяйте обрезку, изменение регистра или обращение строки в один повторно используемый шаг.

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

local function compose(f, g) return function(x) return f(g(x)) end end

local shout = compose(string.upper, string.reverse)
print(shout("lua"))

Композиция множества функций

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

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

local function composeAll(...)
  local fns = {...}
  return function(x)
    for i = #fns, 1, -1 do
      x = fns[i](x)
    end
    return x
  end
end

local f = composeAll(function(n) return n + 1 end,
  function(n) return n * 2 end,
  function(n) return n - 3 end)
print(f(10))

Справа налево

В composeAll(a, b, c) сначала выполняется крайняя справа функция c, затем b, а потом a. Это соответствует вложенной форме a(b(c(x))).

Порядок бывает трудно читать, поэтому некоторые предпочитают использовать конвейер слева направо.

Конвейер слева направо

pipe меняет порядок чтения на обратный: функции выполняются слева направо, в записанном порядке. Многие считают такой порядок более понятным при работе с конвейерами данных.

Цикл проходит вперёд, применяя каждую функцию к текущему значению.

local function pipe(...)
  local fns = {...}
  return function(x)
    for i = 1, #fns do
      x = fns[i](x)
    end
    return x
  end
end

local process = pipe(function(n) return n + 1 end,
  function(n) return n * 2 end)
print(process(5))

Конвейер для наглядности

С помощью pipe шаги читаются сверху вниз в порядке выполнения. Это делает многоэтапные преобразования наглядными сами по себе.

Здесь из строки сначала удаляется заданный префикс, затем она переводится в нижний регистр, а после этого обращается; каждый шаг перечислен в порядке выполнения.

local function pipe(...) local fns={...} return function(x) for i=1,#fns do x=fns[i](x) end return x end end

local transform = pipe(string.lower, string.reverse,
  function(s) return "[" .. s .. "]" end)
print(transform("LUA"))

Композиция с замыканиями

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

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

local function pipe(...) local fns={...} return function(x) for i=1,#fns do x=fns[i](x) end return x end end
local function adder(n) return function(x) return x + n end end
local function muller(n) return function(x) return x * n end end

local calc = pipe(adder(3), muller(10))
print(calc(2))

Композиция и конвейеры

Композиция лежит в основе конвейеров обработки данных. Вместо глубокого вложения вызовов один раз присвойте имя составной функции и применяйте её ко множеству входных данных.

Особенно хорошо это работает с отображением: передайте составную функцию как преобразование для каждого элемента.

local function map(t, f) local o={} for i,v in ipairs(t) do o[i]=f(v) end return o end
local function compose(f, g) return function(x) return f(g(x)) end end

local step = compose(function(n) return n + 1 end, function(n) return n * n end)
local r = map({1, 2, 3, 4}, step)
print(table.concat(r, ", "))

Делайте функции небольшими

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

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

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

Перед ответом внимательно проследите за порядком выполнения.

Итоги

Композиция объединяет функции так, что выходные данные одной передаются следующей. compose(f, g) выполняет g, а затем f, то есть работает справа налево, тогда как pipe выполняет функции слева направо, что повышает наглядность.

С помощью composeAll и pipe Вы можете объединять множество небольших функций в понятные конвейеры, особенно эффективно сочетая их с отображением.

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

Урок «Композиция функций» бесплатный?

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

Чему я научусь в уроке «Композиция функций»?

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

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

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

Сколько времени занимает урок «Композиция функций»?

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

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

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

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

  1. Функции как значения
  2. map, filter, reduce
  3. Частичное применение
  4. Композиция функций
← Назад к Lua Academy