2

I have these two functions where i am trying to modify the elements. One of them compiles and other says 'val cannot be reassigned'. What is the difference between the following functions? Why does one compile and the other does not?

The one that compiles

fun <T> Array<T>.mapInPlace2(transform: (T) -> T) {
for (i in this.indices) {
    this[i] = transform(this[i])
}
}

The one that says

Val cannot be reassigned

fun <T> Array<T>.mapInPlace1(transform: (T) -> T) {
for (i in this) {
    i = transform(i);
}
}
Dishonered
  • 8,449
  • 9
  • 37
  • 50

3 Answers3

6

Similiarly to how function parameters are final in Kotlin, so are the variables used in for loops. Essentially, writing down...

for (i in array) {
    ...
}

... is the equivalent of doing this in Java:

for (final int i : array) {
    ...
}

This helps catch some common errors, in this case - if the compiler allowed you - you'd be reassigning this local variable that just contains a reference to the real element, without changing the array. In Java terms, you'd be doing this:

for (int i : array) {
    i = transform(i);
}

This new value of i is unused, it doesn't change the array itself, and it will be immediately overwritten by the value of the next element when the loop comes around.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
3

Try this:

for(i:Int in 0 until this.size) {
    this[i] = "your value"
}
A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
1

You're confusing the mutability of references to objects and objects themselves.

In the first example, the structure is mutable, but the reference to it is immutable. You can change the structure of the object itself, but you can't change what structure the references points to.

In the second example, you're trying to change an immutable reference to an object, not the object itself.

If you write

val i = obj

obj can still be mutated if it's a mutable object. i can't be reassigned though, sine the reference can't be changed.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117