Kotlin Academy · Урок

Когда что использовать

Компромиссы

Урок 4 из 413 шагов

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

Два инструмента — разные задачи

Инфиксные функции предназначены для читаемости, а функции с модификатором tailrec — для безопасной и эффективной рекурсии. Они решают разные задачи.

infix fun Int.add(o: Int) = this + o

tailrec fun sum(n: Int, acc: Int = 0): Int =
    if (n == 0) acc else sum(n - 1, acc + n)

fun main() {
    println(2 add 3)
    println(sum(10))
}

Выбирайте инфиксные функции для выразительных API

Выбирайте инфиксную запись, когда вызов становится понятнее без точек и скобок, особенно в DSL и при создании пар.

fun main() {
    val pair = "id" to 100
    println(pair)
}

Выбирайте tailrec для глубокой рекурсии

Используйте tailrec, когда рекурсивный алгоритм может быть достаточно глубоким, чтобы вызвать переполнение стека.

tailrec fun count(n: Int, acc: Int = 0): Int =
    if (n == 0) acc else count(n - 1, acc + 1)

fun main() {
    println(count(50000))
}

Компромиссы инфиксной записи

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

infix fun Int.scaledBy(f: Int) = this * f

fun main() {
    println(5 scaledBy 3)
}

Компромиссы tailrec

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

tailrec fun product(n: Int, acc: Long = 1): Long =
    if (n <= 1) acc else product(n - 1, acc * n)

fun main() {
    println(product(6))
}

Когда цикл проще

Если обычный цикл for или while понятнее хвостовой рекурсии, выбирайте цикл. Рекурсия — это инструмент, а не обязательное требование.

fun sumLoop(n: Int): Int {
    var total = 0
    for (i in 1..n) total += i
    return total
}

fun main() {
    println(sumLoop(10))
}

Когда именованный вызов понятнее

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

data class Temp(val c: Int) {
    fun isWarmerThan(o: Temp) = c > o.c
}

fun main() {
    println(Temp(30).isWarmerThan(Temp(20)))
}

Сочетание обоих подходов

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

infix fun Int.upto(n: Int) = (this..n).toList()

tailrec fun last(list: List<Int>): Int =
    if (list.size == 1) list[0] else last(list.drop(1))

fun main() {
    println(last(1 upto 5))
}

Проверка читаемости

Спросите себя: делает ли инфиксная запись вызов понятнее новичку? Предотвращает ли tailrec реальный риск переполнения стека? Если нет, отдайте предпочтение обычным функциям и циклам.

fun main() {
    val r = (1..5).sum()
    println(r)
}

Примечание о производительности

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

tailrec fun pow(base: Int, exp: Int, acc: Long = 1): Long =
    if (exp == 0) acc else pow(base, exp - 1, acc * base)

fun main() {
    println(pow(2, 10))
}

Краткое руководство по выбору

Инфиксная запись: выразительные двоичные вызовы с одним аргументом. Tailrec: рекурсия, которая должна безопасно обрабатывать большие объёмы данных. Ни один из вариантов не является выбором по умолчанию — оба требуют осознанного решения.

infix fun String.joinWith(o: String) = "$this-$o"

fun main() {
    println("a" joinWith "b")
}

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

Проверьте, насколько хорошо Вы поняли, когда использовать каждую возможность.

Итоги

Вы узнали, когда использовать каждую возможность:

  • Используйте infix для выразительных и читаемых двоичных вызовов и DSL.
  • Используйте tailrec для рекурсии, которая должна масштабироваться без переполнения стека.
  • Отдавайте предпочтение обычным циклам или именованным функциям, если они понятнее.
  • Эти две возможности независимы и могут сочетаться.
infix fun Int.by(o: Int) = this * o
tailrec fun dec(n: Int): Int = if (n == 0) 0 else dec(n - 1)

fun main() {
    println(3 by 4)
    println(dec(1000))
}
Можно начать бесплатно

Изучай Kotlin с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

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

Урок «Когда что использовать» бесплатный?

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

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

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

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

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

Сколько времени занимает урок «Когда что использовать»?

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

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

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

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

  1. Инфиксные функции
  2. Создание API в стиле DSL
  3. Функции tailrec
  4. Когда что использовать
← Назад к Kotlin Academy