is there any way to get a reference to a property?...
# announcements
t
is there any way to get a reference to a property? I can do this:
fun <T> foo(t: T, setProp: T.(Int) -> Unit, getProp: T.() -> Int) = t.apply { setProp(getProp() + 1) }
but what I want to do is:
fun <T> foo(t: T, prop: Property<T,Int>) = t.apply { prop += 1 }
d
val prop: K(Mutable)Property1<MyClass, Int> = MyClass::property
should do what you want.
t
the problem is that I have to write
prop.set(t, prop.get(t) + 1)
then which defeats the purpose of making the syntax nicer.
tbh I doubt it's even possible but maybe some Kotlin guru here has an idea
d
The best I got is this, if you can use a property without a receiver (e.g. with a bound reference):
Copy code
operator fun <R> KProperty0<R>.getValue(receiver: Nothing?, p: KProperty<*>) = get()
operator fun <R> KMutableProperty0<R>.setValue(receiver: Nothing?, p: KProperty<*>, value: R) = set(value)

fun foo(property: KMutableProperty0<Int>) {
    val prop by property
}
Unfortunately there is no API to turn a
KProperty1<T, R>
and a receiver value
T
into a
KProperty0<R>
yet.
t
I guess I'll have to stay with regular functions then, but thanks anyway
d
Well, you can still use
KProperty1
, makes it easier for the caller of your function
t
yeah but at the expense of readability of my function, which is already quite complex and the call site will just be copy&paste boilerplate, where bugs are unlikely
d
Up to you 🤷
t
My use case is that I have a function that returns an observable of anonymous functions which should mutate some state. But I want the function to work with different state classes, so I have to glue them together somehow
currently I pass getters and setters for all the required fields as function parameters, but I'm looking for other solutions
d
I think using a
KProperty
would be cleaner overall, but I can see why you don't want to do it.
t
the functions look like this:
Copy code
fun <S : State, V : View<S>, T> handlePagination(loadNextPage: () -> Single<List<T>>,
                                                 endReachedSignal: Observable<*>,
                                                 getCurrentState: () -> S,
                                                 getList: S.() -> List<T>,
                                                 setList: S.(List<T>) -> Any?,
                                                 setLoading: S.(Boolean) -> Any?,
                                                 showPagingFailed: V.() -> Any?)
        : Observable<ProgramUpdate<S, V>> {

    fun load() = just(StateChange<S, V> { setLoading(true) })
            .then(loadNextPage().retryDelayed(delay = 1000, times = 5)
                          .map<ProgramUpdate<S,V>> { nextPageItems ->
                              StateChange {
                                  setList(getList() + nextPageItems)
                              }
                          }
                          .onErrorReturn {
                              Timber.e(it)
                              ViewAction(showPagingFailed)
                          }
            )
            .then(StateChange<S, V> { setLoading(false) })

    fun initList() =
            if (getCurrentState().getList().isEmpty())
                load()
            else
                never()

    return merge(endReachedSignal.dropMap { load() }, initList())
}
so you can see why I want to make them simpler