Why was the indexed for loop removed in Kotlin?

Viewed 19854

I still think "traditional" way of using the for loop is very powerful with full control of the index. Why was it removed in Kotlin?

what should I do in kotlin with following java code

for (int i = 0; i < n - 1; i++) {
   for (int j = i + 1; j < n; j++) {
   ....
14 Answers

Another useful way of retaining those indexes white iterating something (an Iterable, that is), is to use the withIndex() method. For example:

for((i, element) in myIterable.withIndex()){
    //do something with your element and the now known index, i
}

This I noticed achieves the same as what suggested in this answer, but I think it is better if we use the already built-in method Iterables have for such situations instead of implementing them again. This we could say is also similar to the forEachIndexed{} lambda:

myIterable.forEachIndexed{i, element ->
    //do something here as well
}

You can use this if you want to get the index and the value at the same time.

for ((index, value) in array.withIndex()) {
    println("the element at $index is $value")
}

This is pretty simple.

Source: Kotlin Official Documentation - Control Flow

It does not make any sense because at times you want to have more custom loops with custom steps and that structure kind of removes that from the logic

var array = ["-m", "/test/app", "-w", "us"];

for (var i = 0; i < array.length; i += 2) {
    console.log("option =" + array[i]);
    console.log("value =" + array[i+1])
}

With the current kotlin loop, we lose some of the simplicity that was there.

Kotlin is trying to enforce fluent iteration, which covers the vast majority of looping constructs. However, I needed a traditional for loop (like java) with an immediately terminating state scope, exit condition that evaluates before loop-body execution, and a post-execution operation (my use case was complicated: I needed to repeat using a dynamic exit condition based on a compression routine and powers of 2). I came up with these general functions:

fun <S> forloop(state: S, condition: (s: S) -> Boolean, postExecution: (s: S) -> Unit, block: (s: S) -> Unit) {
  while (condition(state)) {
    block(state)
    postExecution(state)
  }
}

data class SingleIndex(var i: Int)
fun forloop(i: Int, condition: (s: SingleIndex) -> Boolean, postExecution: (s: SingleIndex) -> Unit, block: (s: SingleIndex) -> Unit) {
  forloop(SingleIndex(i), condition, postExecution, block)
}

Examples here:

fun main() {
    forloop(0, {it.i < 10}, {++it.i}) {
        println("forloop test: i=${it.i}")
    }

    data class State(var i: Int, var j: Int)
    forloop(State(0, 1), {it.i < 10}, {++it.i; it.j += it.i}) {
        println("forloop test: i=${it.i}, j=${it.j}")
    }
}

Although, in compliance with the language philosophy, you should only use this in rare circumstances.

generateSequence(0) { it + 2 }.takeWhile { it < array.length }.forEach {
    // Do something useful
}

For this exact case the following double loop can be used:

for (i in 0 until n) {
        for (j in (i + 1) .. n) {
for (i in generateSequence(0) { it + 2 }.takeWhile { it < array.length }) {
    // do something useful
}
Related