Drawing with ReactiveX: https://bitbucket.org/snippets/sglienke/BEXnM9

Drawing with ReactiveX: https://bitbucket.org/snippets/sglienke/BEXnM9

Yes, the classic approach would be way less code but you get the idea of how you can combine multiple event streams to achieve these things.

Still looking for ways to reduce the generic argument cluttering.

FWIW here is the same example in JS: https://codepen.io/HunorMarton/pen/mWVVXg

Links to the feature requests mentioned in the comments (please vote):
https://quality.embarcadero.com/browse/RSP-16763
https://quality.embarcadero.com/browse/RSP-10336

Comments

  1. Why do you need to explicitly subscribe on main thread? Shouldn't this be set by default?
    It looks like you needed to introduce some "hacks" because of the lack of some language features. It is a pity that it is not possible to express original ideas from Rx without these "hacks".
    Are you planning to add support for backpressure?
    Also, I was not able to find flatMap operator in rx branch. Map and FlatMap are essential operators in reactive programming.

    ReplyDelete
  2. Interesting approach. Where does the concurrency come in?

    (Tracking a single mouse wouldn't seem to imply the need for concurrency. OTOH, at first glance, this code appeared to be some kind of "mouse event macro recorder / player". So you could easily have multiple independent streams of mouse events "playing back" and simultaneously rendering something on a canvas (or multiple canvases) much faster.)

    ReplyDelete
  3. I was lucky enough to have a demo last Tuesday (thanks Stefan!) Re the scheduling, if I remember correctly the code can run on any thread, and often will. Scheduling is used to pull it back to the main thread.

    ReplyDelete
  4. David Millington Rx should be single threaded by default. If you want to perform some work on other threads (not the current thread) , you need to explicitly define this by using observeOn and/or subscribeOn and set needed schedulers.

    ReplyDelete
  5. Linas Naginionis I am currently following the .NET implementation/naming pattern (makes it easier during development) until I finish all/most operators and then look again on how to change certain things (for example the naming for debounce and throttle in RX.NET are kinda confusing - and not just for me as google searches show).

    The implementation is thread agnostic and subscribers act in the thread that produces things unlike specified otherwise. However I will look into making these special observables that come from UI events (via FromEventPattern observeon(mainthread) by default)

    Yes, there are some "hacks" (you probably noticed the _ method) that I needed to keep chaining methods together that you could not otherwise because generic parameters on interface methods are not allowed. I keep bugging any possible Embarcadero person about this for quite a while now (interface/generic types helpers).

    The map operator is called Select in .NET (and is consistent with the naming in IEnumerable). flatmap is typically SelectMany.

    What are you calling "support" for back pressure? Typically you have to use some operators that make sure that for example when zipping two sequences and one produces twice as fast as the other you wont get an out of memory at some point.

    David Schwartz You could use it to record events - you would just need something to store and then replay at will.

    What operators operate in threads is implementation detail though many provide an overload where you can pass a scheduler which controls where and when things get executed - there are some built-in but you can implement your own.

    I typically always add the ObserveOn(MainThread) before some UI subscriber even when I know the code at that point is executed completely in the same thread because you might insert some operator that kicks off something in another thread.

    RX.NET has an extension method called SubcribeOnDispatcher which does what ObserveOn(MainThread).Subcribe(...) does.

    Because I cannot add extension methods for IObservable for now I don't implement methods on it that just duplicate or combine functionality that you already have. Again I am asking for generic/interface helpers for quite a time now with limited success so far.

    ReplyDelete
  6. Stefan Glienke Operators in Rx could be made backpressure aware (it is implemented in RxJava but not in .NET) - in this case they will automatically slow down the producer if the downstream consumer can't keep up.

    ReplyDelete
  7. Linas Naginionis Yes, I know that and I think this should not be baked into the operators. You can easily use similar approach as replay subject to cap the backpressure by some operator like Latest(x) or something (if just adding new methods to IObservable would be easy...).

    ReplyDelete
  8. +100 on interface and generic helpers, and more than one helper in scope.

    ReplyDelete
  9. Very nice. I attempted the same thing a while back, but got too frustrated by the lack if language features and all the hacks and just gave up, with the intention to revisit IF the language ever improves enough (not holding my breath).

    ReplyDelete
  10. Stefan Glienke where do i get for berlin ?
    Spring.Reactive,
    Spring.Reactive.Concurrency;

    ReplyDelete
  11. shlomo abuisak Spring4D feature/1.3-rx branch - still work in progress though

    ReplyDelete

Post a Comment