Расскажите о функциях высшего порядка. Когда они нужны?android-243

1. Определение

Функция высшего порядка (Higher-Order Function) — это функция, которая:

  • Принимает другие функции в качестве параметров или
  • Возвращает функцию как результат

2. Базовый синтаксис

fun higherOrderFunction(callback: (Int) -> String): String {
    val result = 42
    return callback(result)
}

3. Основные сценарии использования

3.1. Колбэки и асинхронные операции

Проблема: Обработка асинхронных результатов
Решение:

fun fetchData(callback: (Result<Data>) -> Unit) {
    thread {
        try {
            val data = api.getData()
            callback(Result.success(data))
        } catch (e: Exception) {
            callback(Result.failure(e))
        }
    }
}

// Использование
fetchData { result ->
    when (result) {
        is Success -> showData(result.data)
        is Failure -> showError(result.exception)
    }
}

3.2. Обобщенные алгоритмы

Пример: Кастомная фильтрация списка

fun List<Int>.filterCustom(predicate: (Int) -> Boolean): List<Int> {
    val result = mutableListOf<Int>()
    for (item in this) {
        if (predicate(item)) {
            result.add(item)
        }
    }
    return result
}

// Использование
val numbers = listOf(1, 2, 3, 4, 5)
val evens = numbers.filterCustom { it % 2 == 0 }

3.3. Инкапсуляция поведения

Паттерн "Стратегия":

fun processPayment(
    amount: Double,
    strategy: (Double) -> Boolean
): Boolean {
    return strategy(amount)
}

// Стратегии
val creditCardStrategy = { amount: Double ->
    /* логика оплаты картой */ true
}
val cryptoStrategy = { amount: Double ->
    /* логика крипто-оплаты */ true
}

// Использование
processPayment(100.0, creditCardStrategy)

3.4. DSL-построение

Пример:

fun dialog(init: DialogBuilder.() -> Unit): Dialog {
    val builder = DialogBuilder()
    builder.init()
    return builder.build()
}

// Использование
dialog {
    title = "Warning"
    message = "Are you sure?"
    positiveButton("Yes") { /* action */ }
    negativeButton("No") { /* action */ }
}

4. Продвинутые техники

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

fun <A, B, C> compose(f: (B) -> C, g: (A) -> B): (A) -> C {
    return { x -> f(g(x)) }
}

val square = { x: Int -> x * x }
val double = { x: Int -> x * 2 }
val squareThenDouble = compose(double, square)

4.2. Мемоизация

fun <T, R> ((T) -> R).memoize(): (T) -> R {
    val cache = mutableMapOf<T, R>()
    return { input -> cache.getOrPut(input) { this(input) } }
}

val expensiveCalculation = { x: Int ->
    Thread.sleep(1000)
    x * x
}.memoize()

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

5.1. Inline-функции

inline fun measureTime(block: () -> Unit): Long {
    val start = System.nanoTime()
    block()
    return System.nanoTime() - start
}

Плюсы:

  • Нет накладных расходов на лямбда-выражения
  • Возможность использования нелокального return

6. Когда не стоит использовать

  1. Простые операции: Если можно обойтись обычными функциями
  2. Критичные к производительности участки: JVM не всегда оптимизирует лямбды
  3. Сложная отладка: Цепочки вызовов могут усложнять дебаггинг

Резюмируем:

функции высшего порядка — мощный инструмент для создания гибкого и переиспользуемого кода. Они особенно полезны для обработки асинхронных операций, реализации паттернов проектирования и построения DSL. Однако требуют взвешенного подхода к применению, особенно в performance-critical участках кода.