react icon indicating copy to clipboard operation
react copied to clipboard

Dynamic E.merge

Open art-w opened this issue 10 years ago • 2 comments

It's currently expensive to merge a dynamic collection of events: The E.merge function only works on a fixed list, so on each change to the list, we need to re-merge it from scratch (and the cost is proportionate to the number of elements in the list, rather than the number of added events.) Alternatively, we can merge the previously merged event with the new ones: This time, we pay a slow down proportionate to the number of updates to the list.

Would it be possible to have an analogue to E.switch, that would compute the "merge" of the inner events efficiently? (rather than their sequencing)

val union : ('a -> 'a -> 'a) -> 'a event -> 'a event event -> 'a event

(* or fold-like, but it looks confusing *)
val union : ('a -> 'b -> 'a) -> 'a -> 'b event -> 'b event event -> 'a event

I personally only care about union f when f is commutative, and I don't believe there's a serious use case for an "ordered dynamic merge", but that's discussable (in practice, the commutative version can be faster -- and the ordered one is recoverable from it.)

art-w avatar May 15 '15 14:05 art-w

val union : ('a -> 'a -> 'a) -> 'a event -> 'a event event -> 'a event

If I'm not mistaken, any event occurring on the higher order event can never be gc'd until the resulting event is. So union looks like a combinator to shoot yourself in the foot (aïe) as it's the kind of event you are likely to have at the toplevel of your program and that you never gc.

dbuenzli avatar May 17 '15 14:05 dbuenzli

Yeah, I do not have a good proposal for a union that lets you remove events in an explicit way (for the gc.) If union doesn't keep a reference to the inner events, then it's up to the user to keep them alive until they are judged unneeded (I don't think this is very intuitive nor coherent with the rest of React api). If union does keep a ref, then the inner events are indeed un-gc-able; maybe union could forget the stopped events to let them be collected (it might not be cheap if done too aggressively.)

The version that specifies explicitly when to remove an event looks very ugly:

val union : ... -> ('a event * unit event) event -> 'a event

because the "natural" way is to call E.until on the user side, rather than passing the (e, stop_e) explicitly to union.

art-w avatar May 17 '15 16:05 art-w