I'm trying to simplify some code. It's of the form...
# getting-started
t
I'm trying to simplify some code. It's of the form:
Copy code
var insideBox: SpanBoxInfo? = null
...
for (spanBoxInfo in spanBoxes(valveSpanList, yAxis, size)) {
    val (_, _, spanRect ) = spanBoxInfo
    if (spanRect.contains(offset)) {
       insideBox = spanBoxInfo
    } else if ...
}
return if (insideBox != null) {
    "inside" to insideBox
} else if ...
I have a preference for
.forEach
and wanted to apply that here. But when I do, the smart null pointer casting doesn't work at the bottom anymore. Why is that?
y
I'd be curious to see if this works with Kotlin 2.0.0-RC1 because it has a lot of smart cast improvements. Regardless, the simplest solution for you would be to use a
lateinit var
I think
j
I'd suggest to go for a more 'functional' approach of using list operators like
first
or
last
. So maybe something like:
Copy code
val insideBox = spanBoxes(valveSpanList, yAxis, size)
   .last { it.spanRect.contains(offset) }

// then, as its a val, the smart null pointer casting should work as usual
2
k
Juan's suggestion is probably the best solution, but out of interest, it seems the reason for this issue is that the compiler thinks that if you put a var inside a lambda, all bets are off (for example, you might pass that variable inside the lambda to another thread). The compiler doesn't seem to check how you use that variable inside the lambda. Minimal reproducible example:
Copy code
fun foo() {
    var v: Int? = null
    // You just need to reference v inside a lambda for the compiler to not
    // know whether v can subsequently change value between check & use
    {
        v = 5
    }
    if (v != null) {
        println(v + 1)  // ERROR: v may be null
    }
}
Update: the above compiles ok with 2.0.0-RC1.