Функции высшего порядка и каррирование
Изучите расширенные функциональные концепции, такие как функции высшего порядка и каррирование, чтобы создавать гибкий и повторно используемый код.
«Функции высшего порядка и каррирование» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 2 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 3 уроков всего.
Раскрываем возможности функций высшего порядка
Добро пожаловать на урок 2! В функциональном программировании функции обладают большой мощью. Они предназначены не только для вычисления значений: с ними можно обращаться как с любыми другими данными.
Это означает, что функции можно передавать другим функциям в качестве аргументов и даже возвращать из них в качестве результатов. Когда функция делает это, её называют функцией высшего порядка (HOF).
- HOF принимают одну или несколько функций в качестве аргументов.
- HOF возвращают функцию в качестве результата.
- Или делают и то и другое!
HOF в действии: `map`
Одной из самых распространённых HOF в Scala является map. Она преобразует каждый элемент коллекции, применяя к нему заданную функцию, и возвращает новую коллекцию.
Попробуйте выполнить этот простой пример:
object Main {
def main(args: Array[String]): Unit = {
val numbers = List(1, 2, 3)
val doubledNumbers = numbers.map(x => x * 2)
println(s"Original: $numbers")
println(s"Doubled: $doubledNumbers")
}
}HOF в действии: `filter`
Ещё одна полезная HOF — filter. Она выбирает из коллекции элементы, соответствующие заданному условию (функции, возвращающей логическое значение), и создаёт новую коллекцию.
Вот как с помощью filter можно найти чётные числа:
object Main {
def main(args: Array[String]): Unit = {
val allNumbers = List(1, 2, 3, 4, 5, 6)
val evenNumbers = allNumbers.filter(x => x % 2 == 0)
println(s"All: $allNumbers")
println(s"Even: $evenNumbers")
}
}Определение собственной HOF
Вы не ограничены встроенными HOF! Вы можете определять собственные функции, принимающие другие функции в качестве параметров. Синтаксис типа функции: (InputType => ReturnType).
В этом примере определяется функция applyOperation, которая принимает значение типа Int и другую функцию op (принимающую значение типа Int и возвращающую значение типа Int).
object Main {
// A HOF that applies an operation to a number
def applyOperation(x: Int, op: Int => Int): Int = {
op(x)
}
def main(args: Array[String]): Unit = {
val result = applyOperation(10, _ * 3) // Pass an anonymous function
println(s"Result of 10 * 3: $result")
val anotherResult = applyOperation(7, _ + 5)
println(s"Result of 7 + 5: $anotherResult")
}
}Анонимные функции и сокращённая запись
При передаче функций в HOF часто используют анонимные функции (их также называют лямбда-функциями). Scala предлагает краткие способы их записи.
x => x * 2: полная запись анонимной функции._ * 2: сокращённая запись анонимной функции с одним параметром.
Оба варианта распространены и делают код короче и понятнее.
object Main {
def main(args: Array[String]): Unit = {
val numbers = List(10, 20, 30)
// Using full anonymous function syntax
val dividedByTwo = numbers.map(x => x / 2)
println(s"Divided by two: $dividedByTwo")
// Using shorthand `_` syntax
val plusOne = numbers.map(_ + 1)
println(s"Plus one: $plusOne")
}
}Знакомство с каррированием
Каррирование — это приём, который преобразует функцию с несколькими аргументами в последовательность функций, каждая из которых принимает один аргумент.
Название происходит от имени логика Хаскелла Карри. В Scala функции с несколькими списками параметров автоматически каррируются.
Вместо f(arg1, arg2) записывают f(arg1)(arg2).
Пример каррирования: списки параметров
Рассмотрим каррирование в действии. Обратите внимание, что add принимает аргументы в двух отдельных списках параметров.
Это позволяет частично применить функцию, создав новые функции с заранее заданными некоторыми аргументами.
object Main {
// A curried function with two parameter lists
def add(a: Int)(b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
// Call the function normally
println(s"5 + 3 = ${add(5)(3)}")
// Partially apply the first argument
val addFive = add(5)_ // `_` tells Scala to treat it as a partially applied function
println(s"5 + 10 = ${addFive(10)}")
println(s"5 + 20 = ${addFive(20)}")
}
}Преимущества каррирования
Зачем использовать каррирование? В функциональном программировании оно даёт несколько преимуществ:
- Частичное применение: создание специализированных версий функции с заранее заданными некоторыми аргументами. Это повышает повторное использование кода.
- Композиция функций: каррированные функции часто проще объединять с другими функциями.
- Вывод типов: иногда помогает механизму вывода типов Scala, особенно при работе со сложными обобщёнными типами.
Каррирование для пользовательских регистраторов
Представьте, что вы хотите создать разные функции регистрации для разных уровней (например, INFO и ERROR), используя при этом одну и ту же основную логику. Каррирование идеально подходит для этого!
Можно определить общую функцию log, а затем частично применить её для создания конкретных регистраторов.
object Main {
def log(level: String)(message: String): Unit = {
println(s"[$level] $message")
}
def main(args: Array[String]): Unit = {
// Create specialized loggers using partial application
val infoLogger = log("INFO")_
val errorLogger = log("ERROR")_
infoLogger("User logged in successfully.")
errorLogger("Failed to connect to database!")
}
}Быстрая проверка: HOF и каррирование
Рассмотрите следующий фрагмент кода Scala:
def calculate(x: Int)(y: Int, op: (Int, Int) => Int): Int = {
op(x, y)
}
val add = (a: Int, b: Int) => a + b
val multiply = (a: Int, b: Int) => a * b
val result1 = calculate(10)(5, add)
val result2 = calculate(2)(3, multiply)Каковы значения result1 и result2?
Повторение: HOF и каррирование
Отличная работа! Вы изучили две мощные концепции функционального программирования:
- Функции высшего порядка (HOF): функции, которые могут принимать другие функции в качестве аргументов или возвращать их в качестве результатов. Они позволяют писать гибкий и повторно используемый код, например с помощью
mapиfilter. - Каррирование: приём преобразования функции с несколькими аргументами в последовательность функций, каждая из которых принимает один аргумент. Оно особенно полезно для частичного применения и создания специализированных функций.
Эти концепции лежат в основе выразительного и модульного кода на Scala!
Часто задаваемые вопросы
Урок «Функции высшего порядка и каррирование» бесплатный?
Да — полный текст урока «Функции высшего порядка и каррирование» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Scala for Backend Engineering & Functional Programming, подпишись на CoddyKit PRO. Курс Scala for Backend Engineering & Functional Programming содержит 3 уроков всего.
Чему я научусь в уроке «Функции высшего порядка и каррирование»?
Изучите расширенные функциональные концепции, такие как функции высшего порядка и каррирование, чтобы создавать гибкий и повторно используемый код. Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?
Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 3.
Сколько времени занимает урок «Функции высшего порядка и каррирование»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?
Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Функции как значения первого класса
- Функции высшего порядка и каррирование
- Неизменяемость и побочные эффекты