raquo/Airstream

Semantics of `toSignal`

cubuspl42 opened this issue · 1 comments

What's the semantics of toSignal?

I guess that it's an operator that takes an initial values, and creates a signal that, whenever an event occurs in the source event stream, switches to that event.

Like FRP stepper.

stepper

(Image from to Reactive Banana documentation)

But how does toSignal achieve this effect, taking into consideration that both EventStream and Signal are "lazy"? How does it ensure that it doesn't "miss" any event (which would be reflected in its state)?

raquo commented

Correct. The resulting signal can miss events if the events are fired while the signal is stopped. Such a situation is possible if the signal has no observers but the stream has observers other than this signal.

I don't like this, but I'm not aware of how this can be implemented any differently while keeping things lazy since the basic tenet of our memory management is that the parent observable must not have a reference to dependent observables that are stopped.

I also don't know how to make things strict (not lazy) without memory management footguns. Originally we used to have a State type which was like Signal but strict, in simple terms it was its own observer, activated immediately upon creation. But that was basically impossible to work with safely, e.g.

val state: State[S] = ??? // When does this state get released?
val models: List[Model] = ???
val views: List[View] = models.map { model =>
  makeView(model, state.map(st => st.filterByModel(model))) // When does THIS state get released?
}

Hope that makes sense, but I can elaborate if not. I'd be curious to know if there are better solutions to this conundrum.

PS I've just enabled discussions on this github project to this kind of talk separate from actionable bugs and feature requests.