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

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

что мне делать в Котлине со следующим java-кодом

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

8 ответов


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

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 

дополнительная информация: диапазоны & петли


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


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

например, в java мы можем создать for-loop следующим образом:

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

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

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

он не был удален. Просто у него другой синтаксис. Эквивалент 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.")
    }
}

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


еще один полезный способ сохранить эти индексы белыми, повторяя что-то (типа 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
}

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

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

Котлин поддерживает только для каждого петли, The для каждого цикл принимает любой Iterables/Arrays / тип имеет iterator оператора.

если вы хотите использовать для каждого петли выражение, Вы можете написать код, как показано ниже, и вы увидите, что для каждого цикл займет больше кода, чем lamda, поэтому API потока и функциональный интерфейс были введены в java-8:

val array  = arrayOf(1, 2, 3)

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

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

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

вы можете создать собственную функцию для того чтобы осуществить "традиционный цикл с полным контролем индекса". Или нетрадиционным. Например, гибридные 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
}

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