jean
09/23/2025, 8:47 PMdata class MyState(val a: String, val b: Int)
class MyStateHolder() {
private val _state = MutableStateFlow(MyState(a = "", b = 0))
val state: StateFlow<MyState> = _state.asStateFlow()
fun updateState(a: String? = null, b: Int? = null) {
_state.update {
it.copy(a = a ?: it.a, b = b ?= it.b)
}
}
}
How would you convert this to functional programming style? Does one uses a top level variable like this?
private val _myState = MutableStateFlow(MyState())
internal val myState = _myState.asStateFlow()
fun updateMyState(
currentState: MyState,
a: String? = null,
b: Int? = null,
) = currentState.copy(
a = a ?: currentState.a,
b = b ?: currentState.b,
)
fun someFunction() {
...
updateMyState(stateFlow.value, "new value", 1)
...
}
Youssef Shoaib [MOD]
09/23/2025, 9:12 PMMyStateHolder
altogether and just pass around a MutableStateFlow<MyState>
, maybe wrapped in a context if you're feeling fancy. Then, I'd use arrow-optics and specifically its Compose compatibility module so that I can do:
myState.updateCopy {
a set foo
b set bar
}
If I were to keep MyStateHolder
, it'd be solely because I can pass it around as a context, and I'd just make it a dumb wrapper around the flow:
class MyStateHolder {
val myState = MutableStateFlow(MyState(a = "", b = 0))
}
context(msh: MyStateHolder)
val myState get() = msh.myState
and again use optics for updating.Ulrich Schuster
09/24/2025, 5:55 AMjean
09/24/2025, 7:26 AMI would get rid ofRight, that’s what I’ve been trying to do yesterday. Thanks for the advice!altogether and just pass around aMyStateHolder
MutableStateFlow<MyState>
Youssef Shoaib [MOD]
09/24/2025, 7:35 AMjean
09/24/2025, 7:41 AMdata class HardwareState(
override val connectionState: ConnectionState,
override val busy: Boolean,
)
Then I have an interface and it’s implementation defining what can be done with the hardware
interface Hardware {
val state: StateFlow<HardwareState>
fun login()
fun doWork()
}
class HardwareType1 : Hardware {
private val _state = MutableStateFlow<HardwareState(...)>
val state = _state.asStateFlow()
override fun login() {
// do some stuff
state.update { it.copy { connectionState = CONNECTED } }
}
override fun doWork() {
if (state.connectionState == CONNECTED) {
// do the actual work
}
}
}
I’ve seen and heard for a while people saying the object used should represent the state itself. Would it make sense in my case to have DisconnectedHardware
and ConnectedHardware
instead. Then the login function can take a DisconnectedHardware
and doWork a ConnectedHardware
. Is that a good idea? Is there a name for this approach over the conventional oop style?Youssef Shoaib [MOD]
09/24/2025, 7:45 AMjean
09/24/2025, 7:47 AM