Range expressions are formed with `rangeTo`

functions that have the operator form `..`

which is complemented by *in* and *!in*. Range is defined for any comparable type, but for integral primitive types it has an optimized implementation. Here are some examples of using ranges

if (i in 1..10) { // equivalent of 1 <= i && i <= 10 println(i) }

Integral type ranges (`IntRange`

, `LongRange`

, `CharRange`

) have an extra feature: they can be iterated over. The compiler takes care of converting this analogously to Java's indexed *for*-loop, without extra overhead.

for (i in 1..4) print(i) // prints "1234" for (i in 4..1) print(i) // prints nothing

What if you want to iterate over numbers in reverse order? It's simple. You can use the `downTo()`

function defined in the standard library

for (i in 4 downTo 1) print(i) // prints "4321"

Is it possible to iterate over numbers with arbitrary step, not equal to 1? Sure, the `step()`

function will help you

for (i in 1..4 step 2) print(i) // prints "13" for (i in 4 downTo 1 step 2) print(i) // prints "42"

To create a range which does not include its end element, you can use the `until`

function:

for (i in 1 until 10) { // i in [1, 10), 10 is excluded println(i) }

Ranges implement a common interface in the library: `ClosedRange<T>`

.

`ClosedRange<T>`

denotes a closed interval in the mathematical sense, defined for comparable types. It has two endpoints: `start`

and `endInclusive`

, which are included in the range. The main operation is `contains`

, usually used in the form of *in*/*!in* operators.

Integral type progressions (`IntProgression`

, `LongProgression`

, `CharProgression`

) denote an arithmetic progression. Progressions are defined by the `first`

element, the `last`

element and a non-zero `increment`

. The first element is `first`

, subsequent elements are the previous element plus `increment`

. The `last`

element is always hit by iteration unless the progression is empty.

A progression is a subtype of `Iterable<N>`

, where `N`

is `Int`

, `Long`

or `Char`

respectively, so it can be used in *for*-loops and functions like `map`

, `filter`

, etc. Iteration over `Progression`

is equivalent to an indexed *for*-loop in Java/JavaScript:

for (int i = first; i != last; i += increment) { // ... }

For integral types, the `..`

operator creates an object which implements both `ClosedRange<T>`

and `*Progression`

. For example, `IntRange`

implements `ClosedRange<Int>`

and extends `IntProgression`

, thus all operations defined for `IntProgression`

are available for `IntRange`

as well. The result of the `downTo()`

and `step()`

functions is always a `*Progression`

.

Progressions are constructed with the `fromClosedRange`

function defined in their companion objects:

IntProgression.fromClosedRange(start, end, increment)

The `last`

element of the progression is calculated to find maximum value not greater than the `end`

value for positive `increment`

or minimum value not less than the `end`

value for negative `increment`

such that `(last - first) % increment == 0`

.

`rangeTo()`

The `rangeTo()`

operators on integral types simply call the constructors of `*Range`

classes, e.g.:

class Int { //... operator fun rangeTo(other: Long): LongRange = LongRange(this, other) //... operator fun rangeTo(other: Int): IntRange = IntRange(this, other) //... }

Floating point numbers (`Double`

, `Float`

) do not define their `rangeTo`

operator, and the one provided by the standard library for generic `Comparable`

types is used instead:

public operator fun <T: Comparable<T>> T.rangeTo(that: T): ClosedRange<T>

The range returned by this function cannot be used for iteration.

`downTo()`

The `downTo()`

extension function is defined for any pair of integral types, here are two examples:

fun Long.downTo(other: Int): LongProgression { return LongProgression.fromClosedRange(this, other, -1.0) } fun Byte.downTo(other: Int): IntProgression { return IntProgression.fromClosedRange(this, other, -1) }

`reversed()`

The `reversed()`

extension functions are defined for each `*Progression`

classes, and all of them return reversed progressions.

fun IntProgression.reversed(): IntProgression { return IntProgression.fromClosedRange(last, first, -increment) }

`step()`

`step()`

extension functions are defined for `*Progression`

classes, all of them return progressions with modified `step`

values (function parameter). The step value is required to be always positive, therefore this function never changes the direction of iteration.

fun IntProgression.step(step: Int): IntProgression { if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step") return IntProgression.fromClosedRange(first, last, if (increment > 0) step else -step) } fun CharProgression.step(step: Int): CharProgression { if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step") return CharProgression.fromClosedRange(first, last, step) }

Note that the `last`

value of the returned progression may become different from the `last`

value of the original progression in order to preserve the invariant `(last - first) % increment == 0`

. Here is an example:

(1..12 step 2).last == 11 // progression with values [1, 3, 5, 7, 9, 11] (1..12 step 3).last == 10 // progression with values [1, 4, 7, 10] (1..12 step 4).last == 9 // progression with values [1, 5, 9]

© 2010–2017 JetBrains s.r.o.

Licensed under the Apache License, Version 2.0.

https://kotlinlang.org/docs/reference/ranges.html