Анонимная функция — это функция, которая не имеет имени и может быть использована непосредственно в месте ее объявления.
Объявление и реализация анонимной функции с блочным телом:
val sum = fun(a: Int, b: Int): Int {
return a + b
}
Здесь переменная sum
хранит ссылку на функцию.
Вызов анонимной функции:
println(sum(3, 5)) // Вывод: 8
В Kotlin анонимные функции часто реализуются с помощью лямбда-выражений, которые являются более компактным и удобным способом записи анонимных функций.
Лямбда-выражения — это способ создания анонимных функций.
Синтаксис лямбда-выражений:
{ параметры -> тело }
- Левая часть (
параметры
): Перечисление параметров функции, разделенных запятыми. - Правая часть (
тело
): блок кода, который выполняется при вызове лямбда-выражения.
Пример лямбда-выражения с двумя параметрами:
{ a: Int, b: Int -> a + b }
Объявление и реализация анонимной функции с помощью лямбда-выражения:
val sum = { a: Int, b: Int -> a + b }
println(sum(3, 5)) // Вывод: 8
Тип функции — это тип данных, который описывает сигнатуру функции, включая типы её параметров и возвращаемое значение. Тип функции может быть использован для объявления переменных, параметров функций и возвращаемых значений.
Синтаксис типа функции
(параметры) -> возвращаемый_тип
Объявление переменной с типом функции
val sum: (Int, Int) -> Int = { a, b -> a + b }
println(sum(3, 5)) // Вывод: 8
Автоматический вывод типов позволяет компилятору самостоятельно определять типы переменных, параметров и возвращаемых значений на основе контекста. Kotlin может автоматически выводить типы функций, если они могут быть определены на основе контекста.
Лямбда-выражение без явного указания типа:
val sum = { a: Int, b: Int -> a + b }
println(sum(3, 5)) // Вывод: 8
Когда лямбда-выражение имеет только один параметр, можно использовать специальное ключевое слово it
для ссылки на этот параметр.
val square: (Int) -> Int = { it * it }
println(square(4)) // Вывод: 16
Захват переменных — это возможность лямбда-выражений использовать переменные из окружающей области видимости.
Доступ к переменной из окружающей области видимости
fun main() {
val multiplier = 3 // Переменная из окружающей области видимости
val multiplyByMultiplier: (Int) -> Int = { it * multiplier }
println(multiplyByMultiplier(5)) // Вывод: 15
}
Изменение переменной из окружающей области видимости
fun main() {
var counter = 0
val incrementCounter: () -> Unit = { counter++ }
incrementCounter()
incrementCounter()
println(counter) // Вывод: 2
}
Замыкание — это функция, которая запоминает состояние окружающей области видимости, даже если эта область видимости уже завершила свою работу.
fun createCounter(): () -> Int {
var count = 0
return { count++ }
}
fun main() {
val counter = createCounter()
println(counter()) // Вывод: 0
println(counter()) // Вывод: 1
println(counter()) // Вывод: 2
}
Функция высшего порядка — это функция, которая принимает другие функции в качестве аргументов или возвращает функцию в качестве результата.
Прием функции в качестве аргумента:
fun applyOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun main() {
val sum = fun(a: Int, b: Int): Int {
return a + b
}
// Вызов функции высшего порядка
val sum = applyOperation(3, 5, sum)
println(sum) // Вывод: 8
}
Возврат функции:
fun createMultiplier(factor: Int): (Int) -> Int {
return { x -> x * factor }
}
fun main() {
// Вызов функции высшего порядка
val double = createMultiplier(2)
println(double(5)) // Вывод: 10
}
Передача лямбда-выражений в функцию — это механизм, который позволяет передавать функции в качестве аргументов функциям высшего порядка:
fun applyOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun main() {
val result = applyOperation(3, 5, { a, b -> a + b })
println(result) // Вывод: 8
}
Когда лямбда-выражение является последним аргументом функции, его можно вынести за скобки вызова функции (т.е. использовать внешние лямбда-выражение):
fun main() {
val sum = applyOperation(3, 5) { a, b -> a + b }
println(sum) // Вывод: 8
val multiply = applyOperation(3, 5) { a, b -> a * b }
println(multiply) // Вывод: 15
}
Ссылка на функцию позволяет ссылаться на функцию как на объект.
Синтаксис ссылок на функции:
::имя_функции
Ссылка на функцию верхнего уровня:
fun greet() {
println("Hello, World!")
}
fun main() {
val greetFunction = ::greet
greetFunction() // Вывод: Hello, World!
}
Ссылка на функцию с параметрами:
fun add(a: Int, b: Int): Int {
return a + b
}
fun main() {
val addFunction = ::add
println(addFunction(3, 5)) // Вывод: 8
}
Передача ссылки на функцию в качестве аргумента:
fun applyOperation(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
fun add(a: Int, b: Int): Int {
return a + b
}
fun main() {
val result = applyOperation(3, 5, ::add)
println(result) // Вывод: 8
}
Ссылки на методы классов пакета kotlin:
fun main() {
val toDouble = Int::toDouble
val d = toDouble(5)
println(d) // Вывод: 5.0
}
Композиция функций — это процесс объединения двух или более функций для создания новой функции. Новая функция применяет первую функцию к своему аргументу, а затем применяет вторую функцию к результату первой функции.
В Kotlin композицию функций можно реализовать с помощью функции высшего порядка compose
, которая принимает две функции и возвращает новую функцию, являющуюся их композицией.
Композиция двух функций:
fun addOne(x: Int): Int = x + 1
fun multiplyByTwo(x: Int): Int = x * 2
val addOneAndMultiplyByTwo = compose(::multiplyByTwo, ::addOne)
fun main() {
println(addOneAndMultiplyByTwo(5)) // Вывод: 12
}
Композиция с лямбда-выражениями:
val addOne: (Int) -> Int = { x -> x + 1 }
val multiplyByTwo: (Int) -> Int = { x -> x * 2 }
val addOneAndMultiplyByTwo = compose(multiplyByTwo, addOne)
fun main() {
println(addOneAndMultiplyByTwo(5)) // Вывод: 12
}
Композиция с использованием оператора andThen
:
val addOne: (Int) -> Int = { x -> x + 1 }
val multiplyByTwo: (Int) -> Int = { x -> x * 2 }
val addOneAndMultiplyByTwo = addOne andThen multiplyByTwo
fun main() {
println(addOneAndMultiplyByTwo(5)) // Вывод: 12
}
Лямбда-выражения можно использовать как рекурсивные функции:
fun main() {
val factorial: (Int) -> Int = { n ->
val factorial: (Int) -> Int = { m ->
if (m == 0) 1 else m * factorial(m - 1)
}
factorial(n)
}
println(factorial(5)) // Вывод: 120
}
Часть I
- Анонимные функции: Напишите четыре лямбда-выражение, которые принимают два числа с плавающей точкой и возвращают соответственно результат их сложения, вычитания, умножения и деления. Присвойте эти лямбда-выражения переменным и вызовите их. Результат вызова выведите в командную строку.
- Передача лямбда-выражений в функцию: Напишите функцию
applyOperation
, которая принимает два целых числа и лямбда-выражение, которое принимает два целых числа и возвращает целое число. Напишите четыре вызова функцииapplyOperation
с двумя целыми числами и лямбда-выражениями, которые возвращают сумму, разность, произведение и остаток от деления двух целых чисел. Результат вызова выведите в командную строку. - Лямбда-выражения с захватом переменных: Создайте переменную
multiplier
типаDouble
и присвойте ей некоторое значение. Напишите лямбда-выражение, которое принимает целое число и возвращает его произведение наmultiplier
. Вызовите это лямбда-выражение с некоторым аргументом. Результат вызова выведите в командную строку. - Лямбда-выражения как параметры по умолчанию: Напишите функцию
repeatString
, которая принимает строку и целое число (количество повторений) и возвращает строку, состоящую из указанного количества повторений исходной строки. Добавьте параметр по умолчанию в функциюrepeatString
, который будет использовать лямбда-выражение для добавления пробела между повторениями строки. Результат вызова выведите в командную строку.
Часть II
- Ссылка на стандартную функцию: Используйте ссылку на стандартную функцию
String::length
для вычисления длины строки. Создайте переменнуюmyString
и присвойте ей значение "Hello, World!". Используйте ссылку на функциюString::length
, чтобы вывести длину строки. - Ссылка на функцию с параметрами: Используйте ссылку на функцию
String::substring
для извлечения подстроки из строки. Создайте переменнуюmyString
и присвойте ей значение "Hello, World!". Используйте ссылку на функциюString::substring
, чтобы извлечь подстроку "World" и вывести её. - Композиция функций: Реализуйте функцию
compose
, которая принимает две лямбда-функции и возвращает новую функцию, которая является композицией двух исходных лямбда-функций. - Рекурсивное применение функции: Реализуйте функцию
applyRecursively
, которая принимает лямбда-функцию и целое числоn
, и возвращает новую функцию, которая применяет исходную функциюn
раз. - Функция высшего порядка с захватом переменной: Реализуйте функцию
createMultiplier
, которая принимает целое числоn
и возвращает лямбда-функцию, которая принимает целое число и возвращает его произведение наn
. - Функция с замыканием: Реализуйте функцию
createCounter
, которая возвращает лямбда-функцию, которая при каждом вызове увеличивает счетчик на 1 и возвращает его значение.
Часть III
- Использование лямбда-выражений для реализации различных алгоритмов сортировки: Реализовать четыре различных алгоритма сортировки массива целых чисел, используя лямбда-выражения для определения порядка сортировки (по возрастанию, по убыванию).
- Анонимные функции
- Передача лямбда-выражений в функцию
- Лямбда-выражения с захватом переменных
- Лямбда-выражения как параметры по умолчанию
- Ссылки на функции
- Композиция функций
- Рекурсивное применение функции
- Функция высшего порядка
- Функция высшего порядка с захватом переменной
- Функция с замыканием