Reputation: 580
In the code below:
var verticesCount: Int // to read a vertices count for graph
// Reading until we get a valid vertices count.
while (!Assertions.checkEnoughVertices(
verticesCount = consoleReader.readInt(null, Localization.getLocStr("type_int_vertices_count"))))
// The case when we don't have enough vertices.
println(String.format(Localization.getLocStr("no_enough_vertices_in_graph"),
Assertions.CONFIG_MIN_VERTICES_COUNT))
val resultGraph = Graph(verticesCount)
we are getting next error on the last line:
Error:(31, 33) Kotlin: Variable 'verticesCount' must be initialized
Assertions.checkEnoughVertices accepts a safe type variable as an argument (verticesCount: Int), so it's impossible for verticesCount to be uninitialized or null here (and we're getting no corresponding errors on those lines).
What's going on on the last line when already initialized variable becomes uninitialized again?
Upvotes: 4
Views: 7025
Reputation: 10469
Well, technically it is possible to assign values to variables in the while condition - and anything else you might want to do there, too.
The magic comes from the also
function:
Try this: (excuse the completely useless thing this is doing...)
var i = 10
var doubleI: Int
while ((i * 2).also { doubleI = it } > 0) {
i--
println(doubleI)
}
Any expression can be "extended" with "something to do" by calling also
which takes the expression it is called upon as the it
parameter and executes the given block. The value also
returns is identical to its caller value.
Here's a very good article to explain this and much more: https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84
Upvotes: 5
Reputation: 32826
The syntax you've used denotes a function call with named arguments, not the assignment of a local variable. So verticesCount =
is just an explanation to the reader that the value which is being passed here to checkEnoughVertices
corresponds to the parameter of that function named verticesCount
. It has nothing to do with the local variable named verticesCount
declared just above, so the compiler thinks you've still to initialize that variable.
In Kotlin, the assignment to a variable (a = b
) is not an expression, so it cannot be used as a value in other expressions. You have to split the assignment and the while-loop condition to achieve what you want. I'd do this with an infinite loop + a condition inside:
var verticesCount: Int
while (true) {
verticesCount = consoleReader.readInt(...)
if (Assertions.checkEnoughVertices(verticesCount)) break
...
}
val resultGraph = Graph(verticesCount)
Upvotes: 9