124

I looked at the documentation for the Ranges and I see no mention of backwards ranges.

Is it possible to do something like:

for (n in 100..1) {
    println(n)
}

And get results:

100
99
98
...
jjnguy
  • 136,852
  • 53
  • 295
  • 323

5 Answers5

207

Use downTo as in:

for (n in 100 downTo 1) {
//
}
Saikat
  • 14,222
  • 20
  • 104
  • 125
Hadi Hariri
  • 4,656
  • 2
  • 24
  • 13
  • 63
    Why it's not "for (n in 100..1)"? Couldn't it be an agreement that if the first number is bigger then a range counts backwards? – x2bool Sep 02 '14 at 10:09
  • 3
    Is there something that excludes the lower limit ? e.g. if I want from 100 till 2. and want to exclude 1. – MobileAppDeveloper Apr 11 '19 at 12:54
  • 4
    @x2bool, though it is useful, there are situations, where it is not. For instance, you want to loop from `0` to `count - 1`, but don't want to check limits (like in Java). If `count` becomes 0, you will have `0 downto -1` which will break an algorythm. – CoolMind Dec 24 '19 at 11:21
  • @MobileAppDeveloper, if limits are integer, you can add `1` to lower limit. – CoolMind Dec 24 '19 at 11:23
  • what's the difference among `down to 1`, `down to 2`, `down to 30`? – inherithandle Jul 15 '21 at 13:31
  • Use `for (n in 100 downTo 1 step 2)` to skip one index. – Chintan Shah Sep 03 '21 at 07:37
28

Just as an example of an universal range function for "for":

private infix fun Int.toward(to: Int): IntProgression {
    val step = if (this > to) -1 else 1
    return IntProgression.fromClosedRange(this, to, step)
}

Usage:

// 0 to 100
for (i in 0 toward 100) {
    // Do things
}

// 100 downTo 0
for (i in 100 toward 0) {
    // Do things
}
letner
  • 621
  • 6
  • 11
  • 4
    So there is no native Kotlin equivalent to this? – andrewgazelka Nov 21 '18 at 14:40
  • 2
    I haven't found one. You can get the same result, for example using [step](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/step.html) function for some Progression, but still need to calculate the step by yourself. I suppose, Kotlin architects want to create a perfectly readable language. That means code execution have to be exactly the same as written, and universal infix function like my "toward" doesn't completely fit to that idea. – letner Nov 23 '18 at 05:05
27

As pointed by others, the correct answer is

for (n in 100 downTo 1) {
    println(n)
}

But why did Kotlin team chose 100 downTo 1 vs 100..1?

I think that the syntax 100..1 would be bad when we try to use variables instead of literals. If we typed

for (n in b..a)

then it wouldn't be clear what loop we wanted to use.

We may have intended to count backwards but if b turns out to be smaller than a, then our program would actually count upwards! That would be a source of bugs.

Escape Velocity
  • 729
  • 1
  • 8
  • 21
13

Reversed ranges are supported using the minus - unary operator as in -(1..100).

To invoke a method on that range, you will then need to surround it with parentheses as in

(-(1..100)).foreach { println(it) }
Gibolt
  • 42,564
  • 15
  • 187
  • 127
Franck Rasolo
  • 539
  • 4
  • 9
  • 7
    Is there any possibility of making the rangeTo() function a bit smarter and handling that automatically? Having a negative range to me means counting from -1 to -100. – jjnguy Mar 05 '12 at 14:05
  • I suggest you take a look at the following issues related to ranges in Kotlin and submit a new issue explaining in detail your suggestion: [KT-861](http://youtrack.jetbrains.com/issue/KT-861), [KT-1045](http://youtrack.jetbrains.com/issue/KT-1045), [KT-1076](http://youtrack.jetbrains.com/issue/KT-1076) – Franck Rasolo Mar 05 '12 at 20:19
  • This doesn't pass static analysis in kotlin 1.3 – npjohns Nov 17 '19 at 06:57
4
(100 downto 1).map{ println(it) }
CoolMind
  • 26,736
  • 15
  • 188
  • 224