https://kotlinlang.org logo
#random
Title
i

iamthevoid

08/27/2021, 2:52 PM
Poor example, but can i somehow use
this
reference in
lazy { }
scope for extension val ? Something like that:
Copy code
val String.something by lazy { "$this$this" }
I understand that
this
in the case is outer scope
but is there some chance to use inner scope using
by
keyword?
this@something
is not working
l

LeoColman

08/27/2021, 5:33 PM
That would lead to some recursion issues, wouldn't it?
r

rtsketo

08/27/2021, 8:41 PM
something
isn't initilized to able to use it. Maybe we can help if you are more specific of what you are trying to do.
y

Youssef Shoaib [MOD]

08/27/2021, 9:00 PM
Something like this should work: (playground)
Copy code
import kotlin.reflect.*
import kotlin.properties.*

private val stringSomethingMap: MutableMap<String, Lazy<String>> = java.util.IdentityHashMap()
val String.something by thisDelegate<String, String> {
    stringSomethingMap.getOrPut(this) {
        lazy { "$this$this" }
    }.getValue(this, it)
}
fun main(){
	println("test".something)
}

interface ReadOnlyPropertyWithThis<T, V> : ReadOnlyProperty<T, V> {
    override fun getValue(thisRef: T, property: KProperty<*>): V = thisRef.getValueWithThis(property)
    fun T.getValueWithThis(property: KProperty<*>): V
}

interface ReadWritePropertyWithThis<T, V> : ReadOnlyPropertyWithThis<T, V>, ReadWriteProperty<T, V> {
    override fun getValue(thisRef: T, property: KProperty<*>): V = super<ReadOnlyPropertyWithThis>.getValue(thisRef, property)
    override fun setValue(thisRef: T, property: KProperty<*>, value: V) = thisRef.setValueWithThis(property, value)
    fun T.setValueWithThis(property: KProperty<*>, value: V)
}

inline fun <T, V> thisDelegate(crossinline getValue: T.(prop: KProperty<*>) -> V): ReadOnlyPropertyWithThis<T, V> = object: ReadOnlyPropertyWithThis<T, V> {
	override fun T.getValueWithThis(property: KProperty<*>): V = getValue(property)
}

inline fun <T, V> thisDelegate(crossinline getValue: T.(prop: KProperty<*>) -> V, crossinline setValue: T.(prop: KProperty<*>, value: V) -> Unit): ReadWritePropertyWithThis<T, V> = object: ReadWritePropertyWithThis<T, V> {
	override fun T.getValueWithThis(property: KProperty<*>): V = getValue(property)
    override fun T.setValueWithThis(property: KProperty<*>, value: V) = setValue(property, value)
}

// Or just make your life easier with this:

object DoubleString {
    operator fun getValue(thisRef: String, prop: KProperty<*>) = "$thisRef$thisRef"
}
The issue is that it is up to the delegate to pass you the
thisRef
or not, and for
lazy
it doesn't make sense because it only gets computed once. This does the trick because it makes a lazy instance for each unique string that passes through it.