С самого начала в Kotlin были введены диапазоны (Range) для упрощения операций с последовательными наборами значений — это унаследовано от языков с лаконичным синтаксисом при работе с числами (например, Python). Кроме того, механизм Range был расширен до Progression, позволяя задавать шаг итерации и поддерживать разные типы чисел, символов.
Итерирование по целым числам, буквам, временным точкам и т. д. часто требует особого синтаксиса и надежной поддержки в стандартной библиотеке, иначе код становится громоздким, нечитабельным и подвержен ошибкам по границам.
В Kotlin есть стандартные типы IntRange, CharRange и LongRange, а также Progression для шаговой итерации. Кроме того, можно определить диапазоны для произвольных сравнимых типов.
// Простой диапазон for (i in 1..5) print(i) // 12345 // Диапазон с шагом for (i in 1..10 step 2) print(i) // 13579 // Обратный диапазон for (i in 5 downTo 1) print(i) // 54321 // Собственный диапазон (например, для Version) data class Version(val major: Int, val minor: Int): Comparable<Version> { override fun compareTo(other: Version): Int = compareValuesBy(this, other, Version::major, Version::minor) } operator fun ClosedRange<Version>.iterator(): Iterator<Version> = object : Iterator<Version> { var current = start override fun hasNext() = current <= endInclusive override fun next() = current.also { current = Version(current.major, current.minor + 1) } } val v1 = Version(1, 0) val v2 = Version(1, 3) for (v in v1..v2) println(v)
Ключевые особенности:
.., downTo, until, stepЧем отличается выражение 1..5 от 1 until 5?
1..5 включает оба конца диапазона: 1,2,3,4,5. 1 until 5 не включает последний элемент: 1,2,3,4.
Можно ли задать диапазон с шагом менее нуля с использованием step?
Нет. Для убывающих диапазонов используйте конструкцию downTo, потом step: 5 downTo 1 step 2 (получите 5,3,1).
Можно ли использовать диапазоны с типами, не реализующими Comparable?
Нет. Для создания диапазона необходимо, чтобы тип поддерживал сравнение. В противном случае компилятор не допустит определение.
В коде вместо 1 until n+1 использован 1..n. Получаем лишний элемент, цикл выходит за пределы допустимого диапазона.
Плюсы:
Минусы:
Используется for (i in 0 until n) для индексации массива длиной n, диапазон строго совпадает с допустимыми значениями индексов.
Плюсы:
Минусы: