Thinking about this a little more: I think the issue that concerns me is that while this design seems suitable for inter-actor observation, it seems unsuitable for intra-actor observation. And seeing as this pitch has been presented in the context of being suitable as a UI observation mechanism, the same-actor properties of this mechanism will be key.
In other observation mechanisms like Combine/KVO it is possible for events from Observer to Observable to be propagated synchronously. This property means that UI events can be delivered and processed in the same event loop cycle that they're generated.
Without this property, UI will feel unresponsive and lacking synchronisation. For example, a shadow effect designed to track your finger will, at best, lag slightly behind and at worst appear to drop frames as multiple observation events bunch together. Or, a touch of a button will appear to have a delay before it's highlighted. Or, a screen with a loading state will often show a flash of a spinner even if its content has been previously cached. Or, Observers that should have their effects synchronised with other Observers will appear to react independently and with random delay... etc.
The reason for this is that both ObservedChanges
and ObservedValues
are asynchronous sequences. And despite the fact that a View
and an Observable
might both exist on the @MainActor
, the fact that the Observable communicates to the View via an asynchronous sequence means that it will always (whether or not map is used) take the following route:
MainActor -> Shared Thread Pool -> MainActor
At minimum this means that events generated in the current event loop cycle, won't be delivered until the next event loop cycle. And at worst, it means that events won't be delivered until some unknown event loop in the future.
As mentioned above, this is because any non-annotated async function will always execute on the shared thread pool. And as both ObservedChanges
and ObservedValues
are asynchronous sequences with non-annotated next()
calls this is the route all events must take. (IIUC.)
Frankly though, even if they didn't, even if the event propagation was going through the equivalent of DispatchQueue.main.async { }
, that would still be too laggy for a UI observation mechanism.
In other words: while Observation events may occur asynchronously, that shouldn't imply that the propagation of those events from Observable to Observer should be asynchronous as well.
For responsive UI, event propagation should very much be synchronous.