null

В Kotlin появился новый оператор

Что представляет собой новый оператор?

И так, в языке 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