The ability to change mutability (or reassignabili...
# language-proposals
f
The ability to change mutability (or reassignability) without coming up with a new name like in Rust would be great. fun f() { var x = 0 val x = x }
14
m
Concrete examples would be helpful here. Depending on the scenario, separating the function into multiple functions may help avoiding the mutable variable.
e
It is actually explicitly supported for a common case of turning a function parameter into a variable:
Copy code
fun f(x: T) {
    var x = x // works
}
🙌 1
m
He’s asking for the other way round - mutable local variable to immutable local variable. Basically saying “I’m done mutating that variable”. The parameter case is good but the other way round.
e
Aha, now I see.
Again it now works when you are in different scopes — you can take
var x
from an outer, class scope, for example, and copy it to your own scope with
val x = x
. Does not work in the same scope in Kotlin. Would be interesting to see some more worked-out examples from the real code where it would help.
f
var
to
val
or
val
to
var
is all the same as long as it is local. Nice, didn't know that it's possible in different scopes. Does now include 1.4.10?
n
@Fleshgrinder the thing about this which I'm not sure you know based on your example is that it goes both ways
in fact, the types can even be different
actually, sorry, the types do have to match. but you can make things mutable that way. And assign them unrelated values. Which all significantly lowers the value of immutable names in a scope anyway.
for the "I'm done mutating this" I've always used a scope function:
Copy code
val x: List = run {
   var x = mutableList<Int>()
   ...
   x
}
f
Matching types is a must, otherwise it's shadowing and that can be terribly confusing. Your example is exactly why I contributed
buildList
and friends but they're still experimental because the builder inference is still experimental and has many edge cases where it doesn't work. I currently have no good example and don't remember the piece of code that I was porting from Rust. But I'm pretty sure it involved some loop that contained breaks and/or continues.
Well, a must if it's in the same scope.
n
I think this is related to https://discuss.kotlinlang.org/t/rust-style-variable-shadowing/16338 Ie, 'changing mutability' from
var
to
val
is just a side effect of allowing shadowing within the same scope
f
Yeah, with this I'd like to withdraw my previous statement regarding shadowing. The examples in the thread are things I've done many times in Rust and super nice. Of course the reasoning to support this in Rust also has to do with lifetime, and issue Kotlin doesn't have to deal with, still nice to have.
n
I think build list is pretty nice for this sort of thing
Though it only saves a few characters vs mutableListOf<Int>.also
f
The main advantage of
buildList
(and friends) over
mutableListOf<Int>().also
(and friends) is that you do not need to specify the types but rather that they are inferred for you. This makes you faster. 🙂
There is, of course, also the
capacity
advantage. Using
buildMap(42) {}
will set the
capacity
to a value that is actually suitable for what you want: it reserves memory for at least
42
elements and will not reallocate anything if you add up to
42
elements. This is something you could only achieve with
HashMap(calcActualMapCapacity(42))
(the
calcActualMapCapacity
would need to be defined by you) and it's a stupid nuance of the Java map implementation that capacity is not what users expect. We abstracted that away so that users don't need to worry about it. 🙂
m
I just ran into a use-case myself: When the
var
is captured by a changing closure smart cast is broken. I’d like to re-assign the
var
to a
val
of the same name and have type safety from that moment on.
Copy code
var x: String? = null
somethingWithClosure { … }
val x = checkNotNull(x)
…
👍 1
f
What is the reason that you cannot do
val x = somethingWithClosure {}
?
m
Right. I have multiple vars, not just one.
Note the double null check
f
For this particular case another Rust feature would actually be nicer (actually I think it works in Java too), and that is that a variable can be defined and assigned later:
Copy code
val a: Int
val b: String
run {
    a = 0
    b = ""
}
println("$a: $b") // `0: `
m
Kotlin can do that too. But the closure is called multiple times. In that case that’s not possible.
n
@Fleshgrinder this is a Kotlin thing too - see https://pl.kotl.in/NupG2gbGq. I just think it's tricky to check once you relate that to closures. Maybe contracts do that
f
Ah, nice! 🙂 @Marc Knaup I guess we have a perfect use case then. 🙂
🎉 1