is there something like `val myVar by lazy{ someth...
# getting-started
x
is there something like
val myVar by lazy{ something() }
, but does not cache the value, but re-evaluates the value every time
myVar
it is access?
myVar
is a local variable
e
Copy code
val myVar
    get() = something()
x
@ephemient excuse me, I should have been clearer. In my case
myVar
is a local variable. Is there a built-in for that? Thank you
e
Copy code
val myVar by ReadOnlyProperty { _, _ -> something() }
you could write your own extension
Copy code
operator fun <T> (() -> T).getValue(thisRef: Any?, property: KProperty<*>): T = invoke()
which would allow you to write
Copy code
val myVar by { something() }
g
why having myVar for this at all? can it be just always call
something()
I feel that it shows intent and behaviour better and would cause unexpected results like: if (myVar == anotherVar || myVar == oneMoreVar)
x
@ephemient thank you so much 😄 @gildor I am trying out kotest. There is this
lateinit var var1
. On JUnit I would just use
get()
to make shortcut to `var1`'s properties, but since this is kotest, everything is stored inside a lambda and
get()
can't be applied to local variables, and I don't want to repeat
var1.p1
. It looks something like this:
Copy code
KotestLambda {
    lateinit var var1:Any
    val p1 by myDelegate{var1.p1}
    beforeTest{
        var1 = initVar1()
    }
    test("test 1"){
        // p1 is accessed multiple times.
    }
}
g
I don’t want to repeat
var1.p1
Personal opinion, I would rather repeat it instead of introducing additional property for this Ehh, this lateinit is really nasty 🙈
// p1 is accessed multiple times.
Can you just declare local p1 on
test 1
level?
x
@gildor how is that
lateinit
nasty? I would like to know more. Of course I can declare it in test 1, but it is also used in many other tests. So, after typing this out for like 20 times, I thought I should make a shortcut.
g
I don’t say that there is a much better solution, I’m not really into this style of testing, but I would expect that just every test calls initVar1() instead of using lateinit
in general I feel that lateinit is always a band-aid for some not very nice interaction Don’t say that I don’t do the same, just feel every time that I (or language, or library which I use) failed %)
x
@gildor yes, I fell the same when I saw lateinit is in Hilt example code. It's always the final solution. Maybe I'm just too lazy here 😅. Thanks for the insight thought
g
Hilt is different story (somewhat) that you cannot use constructor injection for things like Activity/Fragment, so yes, it’s the case when Language + Framework (Android) + DI injection library all failed a bit with this interaction, so you have to use lateinit (though way how Android creates Activities is the main reason) So this why limit usage of it to 1-2 properties per activity to inject only something like ViewModel is way to fight with it
x
absolutely
g
Still, why you cannot just do:
Copy code
test("test 1") {
   val p1 = initVar1().p1
}
x
same old story, i don't want to repeat writing that. My app is fairly large, and there are a lot of tests (a lot, a lot) in it, repeating just a single line become a real issues. So I put the initVar1() into beforeTest, and make p1 the shortcut.
e
as a tangent, https://developer.android.com/reference/android/app/AppComponentFactory can enable
class MyActivity @Inject constructor(...)
etc. on Android 9+, and somebody sufficient motivated could use
AsmClassVisitorFactory
to bring that to older APIs. but that's pretty far astray from this topic :)
😲 1
g
Yep, aware about this API Also that it’s already possible with Fragments, but still, it’s not very practical for Activity, looks that attempt to solve lateinit with bytecode manipulation is case when cure worse than the disease