Change `Update` to providing current state as receiver
Closed this issue · 3 comments
So I've been using Eiffel in my side-project for a bit now. And I've made a handful of Update
's, and there's just one small thing that I feel like may improve QoL a little.
So currently the helper update
takes a (State, Action) -> State
lambda. I want to hear your thoughts on changing (or creating a new extension) that takes a lambda scoped to the State
.
Something like:
fun <S : State, A : Action> update(block: S.(action: A) -> Unit): Update<S, A> {
return object : Update<S, A> {
override fun invoke(state: S, action: A) = state.apply { block(state, action) }
}
}
It would allow for more concise Update
code.
Like:
...
update = update { action ->
when(action) {
is Action.Loading -> copy(loading = true)
is Action.Success -> copy(loading = false, list = action.payload)
}
}
Again it's a small change, but it could be nice. One reason I like it is because my linter has a strict 100 character line limit, and saving 6 characters on each line is wonderful.
I'm always a bit cautious with receivers, especially in public APIs but since it's a pure function, possible clashes with other this
are very unlikely.
One goal I have for 5.0.0 though is to provide the same functionality for all users as much as possible, regardless of whether they're using an object oriented or more functional approach. So if they happen to create a class that implements Update
, it should also provide them with the State
receiver.
I'm doing something similar for the bindable mapping I'm currently working on. So I would change Update
to something like this:
abstract class Update<S : State, A : Action> {
abstract fun S.perform(action: A): S
operator fun invoke(state: S, action: A) = state.perform(action)
}
fun <S : State, A : Action> update(perform: S.(action: A) -> S): Update<S, A> {
return object : Update<S, A>() {
override fun S.perform(action: A) = perform(action)
}
}
Note that you don't have to use apply
if you simply return S
from perform
and don't need to pass the receiver as the first parameter. You can use normal extension syntax like you would from outside the class or function.
So feel free to modify it and create a PR if you want.
I look into it this weekend! 💯
Had a busy weekend/week, but I got the PR up.