Question about use of lateinit var: I’ve only seen...
# getting-started
r
Question about use of lateinit var: I’ve only seen it used in class variables, but I recently came across it in a PR from someone new to Kotlin that used it inside a method call. What are the patterns and advice for using lateinit var inside methods? Or should it be avoided? Is the below use of lateinit valid?
Copy code
fun degreesToDirection(degrees: Float?): Direction {
            var smallestDistance: Float = Float.POSITIVE_INFINITY
            lateinit var direction: Direction

            degreesMapping.entries.forEach {
                if (abs(it.value - (degrees ?: 0f)) < smallestDistance) {
                    direction = it.key
                    smallestDistance = (degrees ?: 0f) -  it.value

                }
            }

            return direction
        }
j
There is nothing really wrong about this
lateinit var
per se. But doing this sort of loop to initialize a variable in Kotlin is usually a smell. For instance, is it expected to iterate over all the mappings here? Usually the first match should stop the loop
j
I can't think a lot about it now, but you probably can change that to reduce + first (or fold + first and so on), so you can avoid mutability. But not sure if the alternative is so readable compared to the current one
v
Copy code
fun degreesToDirection(degrees: Float?) =
    degreesMapping.minByOrNull { (_, mappedDegrees) ->
        abs(mappedDegrees - (degrees ?: 0f))
    }!!.key
For instance, is it expected to iterate over all the mappings here? Usually the first match should stop the loop
First match, when searching for a minimum? 😉
😄 2
As far as I understood, lateinit is practially always a smell, be it as property or not and is mainly for integrate into existing frameworks like Spring that sets the value after creating the object and similar.
j
Lol indeed for a minimum you have to, I actually didn't really read the code in details (I'm on mobile) but the general pattern of declaring a var and init via a loop seemed wrong
s
isn't there `minBy`/`maxBy` for this kind of stuff?
v
Yes, I just gave the imho proper code, just see my first comment
j
In Kotlin 1.7 you shouldn't need
minByOrNull
+
!!
v
Which else would I use? I only found
minBy
which is deprecated and should be replaced by
minByOrNull
.
j
they removed minBy in 1.6 to bring back it in 1.7
the previous implementation of minBy can be nullable, so to follow the standard naming, they removed for one version so they can have both, minBy and OrNull in 1.7
v
I see o_O
Or
Copy code
fun degreesToDirection(degrees: Float?) =
    degreesMapping.minWith(compareBy { (_, mappedDegrees) ->
        abs(mappedDegrees - (degrees ?: 0f))
    }).key
And https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/min-by.html shows
minBy
only not deprecated for common, js, and native, but deprecated for jvm
🤔 1
v
Maybe a documentation problem due to the back and forth with deprecation?
r
Wow thanks for the good discussion! Good to know