0

I did this in F# for FRP that works simply as expected:

let print = fun a -> printf "%A\n" a

let event = new Event<_>()
let stream = event.Publish

stream |> Observable.add (fun event -> event |> print)

event.Trigger 5

Although I don't like much about event.publish system, at least, event.Trigger is somewhat straight forward to understand.

Now, I try to get to used to https://reactivex.io/

I have recognized Rx for a long time since its beta release, and I also know this API is very complicated just to do FRP, like with many "rules" like observable / observer and subjectetc., in my view, this is against KISS principle, so haven't touched.

In fact, a weird thing is for an unknown reason, I can't figure out how to do event.Trigger in Rx.

Surely, I googled a lot, and found a little information for this:

RxJS: How would I "manually" update an Observable?

According to this QA, the code for RxJS is

var eventStream = new Rx.Subject();

var subscription = eventStream.subscribe(
   function (x) {
        console.log('Next: ' + x);
    },
    function (err) {
        console.log('Error: ' + err);
    },
    function () {
        console.log('Completed');
    });

var my_function = function() {
  eventStream.next('foo'); 
}

After many trials, I finally discovered that the code below works, with luck

let stream2 = 7 |> Subject.behavior

stream2
|> Observable.map id
|> Observable.subscribe print
|> ignore

stream2.OnNext 99

However, unfortunately, this is only my Guess simply because there's no such a documentation in https://reactivex.io/documentation/subject.html and there is an external documentation http://xgrommx.github.io/rx-book/content/subjects/subject/index.html

The all I know is this code works as intended.

So, my question here is

Is this the only way to "trigger the value" based on the Rx API design?

SmoothTraderKen
  • 602
  • 4
  • 16
  • 1
    I found this series about Rx quite easy to follow, perhaps it will help you with your problem as well. https://rehansaeed.com/reactive-extensions-part1-replacing-events/ – Piotr Rodak Sep 09 '22 at 14:28

1 Answers1

0

You seem to undestand Rx basic terms: IObservable and IObserver. These API:s aren't really that complicated. F# makes it even easier since Events implement IObservable out of the box.

It seems that by trigger you mean "make an Observable emit a value" ( OnNext):

  • If your Observable is created from certain events, triggering such an event will produce a value.

  • If you want to programatically produce a value using a Subject is fine. As stated in the documentation you pasted, it implements both IObservable and IObserver. E.g. you can call OnNext and Subscribe for the object.

I suggest you consider if and why you really need to programatically produce a value in the Observable. Usually you don't since Observables are created from event sources outside your code. Some cases justify using a Subject such as writing unit tests.

supertopi
  • 3,469
  • 26
  • 38
  • Thanks. Well, the complication can be a relative and subjective term, but in order to make "stream" it is definitely unnecessary and the existence of the native `IObservable` out of the box in F# is nothing to do with the complication of the criteria. – SmoothTraderKen Sep 14 '22 at 01:38
  • In fact, the simplest structure of "stream" in math is endo-Functor or Monad, and I implemented them in Haskell by myself. https://gist.github.com/stken2050/8a48153eab0429babe67875459eed8e6 and IMO, the reason FRP is considered as the difficult thing is Rx employed unnecessary complication of Observable and Observer. As a consequences, it seems FB programmer seems to have avoided understanding the simple FRP concept, and they invented the false State management. – SmoothTraderKen Sep 14 '22 at 01:42
  • Also, I did consider the importance to add values to a stream. Your opinion that it is only justified in unit tests is not correct because your premise is only justified If the stream API covers and provides everything to the API users. How are you so sure any events could be converted to streams? The API on the false premise is a bad design. – SmoothTraderKen Sep 14 '22 at 01:51
  • Your last question is already addressed in the answer: Events in F# implement `IObservable` out of the box. This is why all events already are subscribable "streams". Also, you can convert almost anything into an Event, so moving to `Observable` should not be difficult. You seem to be very biased against Rx. In the future, please try to keep questions less opinionated and more technical. – supertopi Sep 15 '22 at 07:17
  • Well, still I can't agree or understand your guideline, so please let me confirm. – SmoothTraderKen Sep 17 '22 at 21:19
  • "*Also, you can convert almost anything into an Event, so moving to Observable should not be difficult.*" For instance, let's consider a simple counter. Surely, there is a timer `Event` that is the F# native first-class object. It shall be very easy to `map` timestamp on UTC or etc., but in many cases, usually we need another indepednnt `countStream` that can be incremental `+1` or sometimes, we need to pause the count nevertheless the timer keeps upating. – SmoothTraderKen Sep 17 '22 at 21:28
  • Imagine Stopwatch. The device can Pause the count, and resume the count. Pause status can be another independent stream. Dependending on the pause status, implement the behavior to `countStream.next(countStream.lastVal + 1)` or do nothing is very easy and simple code; however, trasnforming from timer Stream and mirging Pause-stream into stopwatch counter is much harder. – SmoothTraderKen Sep 17 '22 at 21:36
  • That is what Rx API forces users do. So I think I'm not biased against Rx, and if you say my analysis is opinionized, your answer based on your mention: "*These API:s aren't really that complicated.*" is also biased and opionised, I beleve. – SmoothTraderKen Sep 17 '22 at 21:38
  • You are correct :) I am biased towards Rx and it is opinionated statement. Most of your follow up questions relate to combining multiple `Observable`s to one. Take a look at https://reactivex.io/documentation/operators.html#combining – supertopi Sep 21 '22 at 10:13
  • 1
    E.g. Stopwatch / Pause problem could be solved with `CombineLatest(stopwatch, paused).Where( !paused )` (pseudocode) – supertopi Sep 21 '22 at 10:17