Kotlin :- Range

Ranges

Range expressions are formed with rangeTofunctions 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 (IntRangeLongRangeCharRange) 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)
}

How it works

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/!inoperators.
Integral type progressions (IntProgression,LongProgressionCharProgression) denote an arithmetic progression. Progressions are defined by the firstelement, the last element and a non-zero step. The first element is first, subsequent elements are the previous element plus step. The last element is always hit by iteration unless the progression is empty.
A progression is a subtype of Iterable<N>, where N is IntLong or Char respectively, so it can be used in for-loops and functions like mapfilter, etc. Iteration over Progression is equivalent to an indexed for-loop in Java/JavaScript:
for (int i = first; i != last; i += step) {
  // ...
}
For integral types, the .. operator creates an object which implements both ClosedRange<T> and *Progression. For example, IntRange implementsClosedRange<Int> and extends IntProgression, thus all operations defined for IntProgression are available forIntRange 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, step)
The last element of the progression is calculated to find maximum value not greater than the end value for positive step or minimum value not less than the end value for negative step such that (last - first) % step == 0.

Utility functions

rangeTo()

The rangeTo() operators on integral types simply call the constructors of *Rangeclasses, 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 (DoubleFloat) 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.toLong(), -1L)
}

fun Byte.downTo(other: Int): IntProgression {
    return IntProgression.fromClosedRange(this.toInt(), 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, -step)
}

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 (this.step > 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, if (this.step > 0) step else -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) % step == 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]
Kotlin :- Range Kotlin :- Range Reviewed by Network security on June 14, 2019 Rating: 5

No comments:

Useful Information

Powered by Blogger.