0Pricing
Scala for Backend Engineering & Functional Programming · Урок

Композиция

andThen и compose

«Композиция» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.

Комбинирование функций

Композиция функций означает построение новой функции путём соединения двух существующих: результат одной становится входом следующей. Для этого Scala предоставляет andThen и compose.

object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val double = (x: Int) => x * 2
    val both = addOne andThen double
    println(both(5))
  }
}

andThen: слева направо

f andThen g сначала выполняет f, затем g. Чтение слева направо соответствует порядку выполнения, что многим кажется интуитивным.

  • (f andThen g)(x) == g(f(x))
object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val triple = (x: Int) => x * 3
    val pipeline = addOne andThen triple
    println(pipeline(4))  // (4 + 1) * 3
  }
}

compose: справа налево

f compose g сначала выполняет g, затем f — в математическом порядке f(g(x)).

  • (f compose g)(x) == f(g(x))
object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val triple = (x: Int) => x * 3
    val pipeline = addOne compose triple
    println(pipeline(4))  // (4 * 3) + 1
  }
}

andThen и compose

Эти операции являются зеркальными:

  • f andThen g = g compose f
  • f compose g = g andThen f

Выбирайте вариант, который естественнее читается в вашей ситуации.

object Main {
  def main(args: Array[String]): Unit = {
    val f = (x: Int) => x + 10
    val g = (x: Int) => x * 2
    println((f andThen g)(3))
    println((g compose f)(3))
  }
}

Объединение нескольких функций

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

object Main {
  def main(args: Array[String]): Unit = {
    val clean = (s: String) => s.trim
    val lower = (s: String) => s.toLowerCase
    val bang  = (s: String) => s + "!"
    val process = clean andThen lower andThen bang
    println(process("  HELLO  "))
  }
}

Композиция изменяет типы

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

object Main {
  def main(args: Array[String]): Unit = {
    val length = (s: String) => s.length
    val isLong = (n: Int) => n > 5
    val check = length andThen isLong
    println(check("scala"))
    println(check("functional"))
  }
}

Тождественная функция

identity возвращает входное значение без изменений. Это нейтральный элемент композиции: f andThen identity == f. Полезен в качестве значения по умолчанию в свёртках и условных выражениях.

object Main {
  def main(args: Array[String]): Unit = {
    val f = (x: Int) => x * 2
    val same = f andThen identity[Int]
    println(same(7))
  }
}

Композиция с помощью reduce

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

object Main {
  def main(args: Array[String]): Unit = {
    val steps: List[Int => Int] = List(_ + 1, _ * 2, _ - 3)
    val pipeline = steps.reduce(_ andThen _)
    println(pipeline(5))  // ((5+1)*2)-3
  }
}

Создание повторно используемых конвейеров

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

object Main {
  def main(args: Array[String]): Unit = {
    val sanitize = (s: String) => s.trim.toLowerCase
    val capitalize = (s: String) => s.capitalize
    val format = sanitize andThen capitalize
    println(format("  aLiCe "))
  }
}

Композиция с map

Составная функция — это всего лишь функция, поэтому Вы можете напрямую передать её в map, чтобы применить весь конвейер к элементам коллекции.

object Main {
  def main(args: Array[String]): Unit = {
    val transform = ((x: Int) => x + 1) andThen ((x: Int) => x * x)
    println(List(1, 2, 3).map(transform))
  }
}

Внимательно анализируйте порядок композиции

Распространённая ошибка — путать andThen и compose. Всегда помните: andThen = сначала эта функция, затем та; compose = в обратном порядке.

object Main {
  def main(args: Array[String]): Unit = {
    val inc = (x: Int) => x + 1
    val sqr = (x: Int) => x * x
    println((inc andThen sqr)(2))  // (2+1)^2 = 9
    println((inc compose sqr)(2))  // (2^2)+1 = 5
  }
}

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

Пусть заданы f и g. Что вычисляет выражение (f andThen g)(x)?

Итоги

Вы изучили композицию функций:

  • f andThen g → g(f(x)) (слева направо)
  • f compose g → f(g(x)) (справа налево)
  • Они являются зеркальными отражениями друг друга
  • identity — нейтральный элемент
  • Списки функций можно объединять с помощью reduce(_ andThen _)

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

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

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

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

andThen и compose Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?

Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

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

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

Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?

Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

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

  1. Функции как значения
  2. Каррирование
  3. Композиция
  4. Замыкания
← Назад к Scala for Backend Engineering & Functional Programming