Mitchell Skaggs
06/05/2021, 7:13 AMState<T>
and MutableState<T>
that read and write eagerly seems to work for now (haven't tested snapshotting extensively yet), but I'm concerned that I might need to be observing some types like dependentStateOf
does. Is there a way to integrate my new state types nicely with the existing state types?Mitchell Skaggs
06/05/2021, 7:13 AMIso
optic:
fun <T, U> MutableState<T>.get(iso: Iso<T, U>): MutableState<U> = IsoMutableState(this, iso)
internal class IsoMutableState<T, U>(
private val state: MutableState<T>,
private val iso: Iso<T, U>
) : MutableState<U> {
override var value: U
get() = iso.get(state.value)
set(value) {
state.value = iso.set(value)
}
override fun component1(): U = value
override fun component2(): (U) -> Unit = { value = it }
}
It seems to work fine, but I don't understand enough about the internals of the Compose state management system to be confident in that assessment.Adam Powell
06/05/2021, 2:11 PMMitchell Skaggs
06/05/2021, 7:24 PMMutableState<U>
from a MutableState<T>
and a Lens<T, U>
with all of the features of derivedStateOf
.Adam Powell
06/05/2021, 7:29 PMmutableStateOf
and friends. Can you give a concrete example of what code patterns you'd like to enable? Given X code that is built using snapshot state, what design or ergonomic problem does adding Lenses solve?Adam Powell
06/05/2021, 7:31 PMmutableStateOf
is already a lens into a particular value in a snapshot and this seems like an attempt to add another layer of the same, but with an expectation that MutableState<T>
would become part of a public API somewhere in order to be used with arrow lenses, except snapshot best practices generally have MutableState
objects hidden as implementation details.Mitchell Skaggs
06/05/2021, 9:44 PMMutableState
that is derived from another MutableState
into a @Composable
for read and write access. This has the same benefits as hoisting the state (https://developer.android.com/jetpack/compose/state#state-hoisting), but is more concise and more powerful (by being able to compose lenses).
I don't think I understand how mutableStateOf
is a lens right now. It can be written to, yes, but it isn't able to be derived from another MutableState
as far as I know. And derivedStateOf
has the opposite problem: it's able to be derived, but not able to be written to. Combining those aspects would make an extremely powerful FRP construct that I believe would make writing reusable and testable code much easier.Mitchell Skaggs
06/06/2021, 5:49 AMThis is the dual ofI'll get around to creating actual tests eventually, but it works in the bidirectional temperature conversion app I created., i.e. the callingget
is the one receiving optional focus of theState
. If the focus can not be found, the resulting state is still updated until the callingPrism
changes.State
Adam Powell
06/06/2021, 2:02 PMAdam Powell
06/06/2021, 2:04 PMI'd like to be able to pass ais a thing you should not want to do. We spent a long time in this space in terms of the designs of Compose's state management and associated patterns, and this always led to dead ends and confused abstractions.[...] into aMutableState
for read and write access.@Composable
Adam Powell
06/06/2021, 2:06 PMAdam Powell
06/06/2021, 2:09 PMvalue: T, onChange: (T) -> Unit
pair of parameters instead because it sets expectations more clearly; onChange
is a request; a polite signal of intent that may be considered and acted upon immediately, later, or not at all. In contrast almost any programmer would expect this test to pass:
val first = foo.value
foo.value = expected
val second = foo.value
assertEquals(expected, second)
Adam Powell
06/06/2021, 2:11 PM() -> T
is always an option.Adam Powell
06/06/2021, 2:14 PMMutableState<T>
promises property access semantics that make it very easy to break other unidirectional data flow principles down the lineAdam Powell
06/06/2021, 2:17 PM@Composable
function parameters of type MutableState<T>
at some point as a result.Adam Powell
06/06/2021, 2:19 PMderivedStateOf
is being positioned above, which I think is its own topic entirely 🙂Mitchell Skaggs
06/07/2021, 2:26 AMMutableState<T>
as an "Atom" (borrowed from Clojure, used here https://github.com/calmm-js/documentation/blob/master/introduction-to-calmm.md#atoms). I believe that the "pair of parameters" style of hoisting state is redundant when a they can be combined into a single object: a lensed atom.Mitchell Skaggs
06/07/2021, 2:31 AM