Почему в Котлине был удален индексный цикл?

Я все еще думаю, что "традиционный" способ использования цикла for очень эффективен с полным контролем индекса. Почему он был удален в Котлин?

что я должен делать в kotlin со следующим кодом java

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

Ответ 1

Ответ таков: потому что они решили удалить его. Вы все равно можете использовать этот синтаксис:

for (a in 1..10) print("$a ")              // >>> 1 2 3 4 5 6 7 8 9 10

for (a in 10 downTo 1 step 2) print("$a ") // >>> 10 8 6 4 2 

Для получения дополнительной информации: Диапазоны и циклы

Ответ 2

Он не был "удален". Дизайн нового языка не начинается с набора функций любого существующего языка; мы начинаем с языка, который не имеет никаких функций, и начинаем добавлять функции, которые необходимы, чтобы выразить определенное поведение красивым и идиоматическим способом. До сих пор мы не знаем о каком-либо поведении, для которого цикл "для" C-стиля был бы самым приятным и самым идиоматичным способом его выражения.

Ответ 3

Я думаю, что причина, по которой они сделали это таким образом ("не удалено"), заключается в том, что они хотели сделать Kotlin более выразительным.

Например, в Java мы можем создать цикл for следующим образом:

for(int x = 1; x <= 10; x++) {
   System.out.print(x);
}

Все, что вы пытаетесь сделать, это то, что вы хотите распечатать значения от 1 до 10, вот и все. Поэтому Котлин решил перевести ваши слова в код и убрать ненужные подробности.

for (x in 1..10) print("$x") 

Ответ 4

Еще один полезный способ сохранить эти индексы в белых итерациях (то есть, Iterable) - это использовать метод withIndex(). Например:

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

Это, как я заметил, достигает того же, что предложено в этом ответе, но я думаю, что было бы лучше, если бы мы использовали уже встроенный метод Iterables для таких ситуаций вместо того, чтобы реализовывать их снова. Мы можем сказать, что это также похоже на forEachIndexed{}:

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

Ответ 5

Он не был удален. Это просто другой синтаксис для него. Эквивалент кода Java:

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

Было бы написано в Котлин таким образом:

val n = 10
for (i in 0..n-2) {
    for (j in i+1..n-1) {
        println("I'm low level for loop! I just look more friendly.")
    }
}

Kotlin использует диапазоны для определения итераторов циклов ради краткости кода.

Ответ 6

Там нет необходимости использовать традиционный for цикла в Котлин, потому что вы можете с помощью Котлин лямбды, чтобы делает ваш код более выразительным и читаемым. например:

arrayOf(1, 2, 3).forEachIndexed { index, item -> /**TODO**/}

Kotlin поддерживает только каждый цикл, для каждого цикла принимает любой Iterable s/Array s/type имеет оператор iterator.

Если вы хотите вернуться к использованию выражения для каждого цикла, вы можете написать код, как показано ниже, и вы можете видеть, что для каждого цикла требуется больше кода, чем lamda, поэтому stream api & функциональный интерфейс был введен в [ TG00]:

val array  = arrayOf(1, 2, 3)

for(index in array.indices){
  val item = array[index]
  // todo
}

Если вам нужно вернуться к традиционным for цикла Вы можете с помощью repeat вместо этого, например:

repeat(5){index-> /**TODO**/}

Ответ 7

Зачем? "Традиционный" цикл является причиной исключения "index out of bounds" в отличие от цикла для элементов коллекции.

Ответ 8

Вы можете создать собственную функцию для реализации "традиционной циклы с полным контролем индекса". Или нетрадиционным. Например, гибрид forEachIndexed(), with(), count() с индексом 1 для подсчета.

inline fun <T> Iterable<T>.forWithIndexed1(action: T.(index: Int) -> Unit): Int {
    var index = 0
    for (item in this) item.action(++index)
    return index
}

Ответ 9

Это не имеет никакого смысла, потому что иногда вы хотите иметь больше пользовательских циклов с пользовательскими шагами, и такая структура удаляет их из логики

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])
}

Ответ 10

Kotlin пытается обеспечить беглую итерацию, которая охватывает подавляющее большинство циклических конструкций. Тем не менее, мне был нужен традиционный цикл for (например, java) с немедленно завершающейся областью состояния, условием выхода, которое оценивается перед выполнением тела цикла, и операцией после выполнения (мой вариант использования был сложным: мне нужно было повторить с использованием динамического выхода условие, основанное на процедуре сжатия и степени 2). Я придумал эти общие функции:

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)
}

Примеры здесь:

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}")
    }
}

Хотя, в соответствии с философией языка, вы должны использовать это только в редких случаях.

Ответ 11

Для этого точного случая можно использовать следующую двойную петлю:

for (i in 0 until n) {
        for (j in (i + 1) .. n) {

Ответ 12

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

Ответ 13

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