
Что представляет собой новый оператор?
И так, в языке Kotlin появилась новый оператор - rangeUntil. Он обозначается символами ..< и предназначен для создания полуинтервалов вида [a,b). В английском языке такие полуинтервалы называются Open Ended Ranges (дословно - интервалы с открытым концом). Круглая скобка в выражении [a,b) означает, что соответствующий конец интервала не принадлежит к рассматриваемому множеству, а квадратная - что, наоборот, принадлежит. Таким образом, [a,b) обозначает множество чисел x, удовлетворяющих неравенствам a⩽x<b.
Зачем необходим новый оператор?
Если говорить о целых числах, то интервалы с ними можно создать следующим образом:
fun main() {
val myRange = 0..10
println(0 in myRange) // true
println(10 in myRange) // true
println(11 in myRange) // false
}
Ничего сложного, верно? Если необходимо создать полуинтервалы, то на помощь приходит функция until:
fun main() {
val myRange = 0 until 10
println(0 in myRange) // true
println(10 in myRange) // false
println(11 in myRange) // false
}
Тоже ничего сверхъестественного. Но давайте продолжим и попробуем создать интервалы из вещественных чисел:
fun main() {
val myRange = 0.0..10.0
println(0.0 in myRange) // true
println(10.0 in myRange) // true
println(11.0 in myRange) // false
}
Всё классно, однако если мы попробуем исключить число 10.0 из интервала:
fun main() {
val myRange = 0.0 until 10.0 // 💣 Compilation Error 💣
println(0.0 in myRange)
println(10.0 in myRange)
println(11.0 in myRange)
}
то получим ошибку компиляции!
Kotlin ругается, когда мы пытаемся использовать until с числами с плавающей точкой.
Как же тогда получить интервал, в который будут включены все числа от 0.0 до 10.0, исключая последнее - 10.0?
Можно попробовать использовать функцию nextDown, но тогда появляются погрешности аппроксимации:
import kotlin.math.nextDown
fun main() {
println(0.0..10.0.nextDown())
// 0.0..9.999999999999998
println(0.0..0.5.nextDown())
// 0.0..0.49999999999999994
}
Очевидно, что для многих практических задач, такое решение может быть не приемлемо и соответственно не применимо.
Здесь как раз и приходит на помощь новый оператор rangeUntil (..<).
Как использовать новый оператор?
На текущий момент оператор rangeUntil является экспериментальной фичей. Поэтому потребуются небольшие настройки, прежде чем Вы сможете его использовать.
И так, в файле build.gradle необходимо добавить следующую строку:
kotlinOptions.languageVersion = "1.8"
А далее в коде использовать хинт @OptIn(ExperimentalStdlibApi::class):
@OptIn(ExperimentalStdlibApi::class)
fun main() {
val myRange = 0.0..<10.0
println(0.0 in myRange) // true
println(9.9999 in myRange) // true
println(10.0 in myRange) // false
}
Это всё, на что способен этот оператор? Нет, он работает и с некоторыми другими классами, например с датами:
fun main() {
val dayOf2022 = LocalDate.of(2022, 1, 1)
val dayOf2023 = LocalDate.of(2023, 1, 1)
val myRange = dayOf2022..<dayOf2023
println(myRange) // 2022-01-01..<2023-01-01
println(dayOf2023 in myRange) //false
}
Вообще, если класс, реализует интерфейс Comparable, то к нему можно применить ..< :
operator fun <T : Comparable<T>> T.rangeUntil(
that: T
): OpenEndRange<T>
Спасибо за внимание :)
Статья основа на труде "There’s a new operator in Kotlin!" автора Nishant Aanjaney Jalan.
Также Вы можете посмотреть интересное видео на эту тему: https://www.youtube.com/watch?v=v0AHdAIBnbs