Comments (7)
Just like for the switchMap
issue, the F# library function most likely isn't dealing with OnComplete (in that case) and OnError (in this case) properly. Back when I opened these issues I had just started learning reactive combinators so it did not feel right for me try and poke around the library, but now I'll finish the Rx GUI examples that I've been doing and if nobody has gotten around to it yet I'll deal with this and the switchMap
issue myself.
I'll admit that in this particular issue having to catch exceptions in choose
is not natural, as you would not expect throw exception in it, but it still it does most likely go against the library design guidelines. Actually there is a paper on Rx specs, but I haven't properly studied it yet. I want to do that as well before trying to make a fix.
from fsharp.control.reactive.
Can you tell what might be happening?
from fsharp.control.reactive.
Ok, now that I am done with what I talked about let me get to this. As it turns out, the fix is really easy. All one needs to do is to change this...
let choose f source =
Observable.Create (fun (o : IObserver<_>) ->
subscribeSafeWithCallbacks
(f >> Option.iter o.OnNext)
o.OnError
o.OnCompleted
source)
...to this.
let choose f source =
Observable.Create (fun (o : IObserver<_>) ->
subscribeSafeWithCallbacks
(fun x -> try f x |> Option.iter o.OnNext with ex -> o.OnError ex)
o.OnError
o.OnCompleted
source)
I've tried it by hand and it works. Now, the next problem is how to write a test for this. Before I can even start that I need to figure out how to build the project. Just doing the build in VS IDE is not working for me.
from fsharp.control.reactive.
I figured out how to build it. There is the build.ps1
script which is runnable from Powershell. I needed to do that first.
from fsharp.control.reactive.
[<Test>]
member __. ``throwing an exception in choose lead to the OnError event firing`` () =
let choose f source =
Observable.Create (fun (o : IObserver<_>) ->
subscribeWithCallbacks
(f >> Option.iter o.OnNext) // Incorrect
//(fun x -> try f x |> Option.iter o.OnNext with ex -> o.OnError ex) // Correct
o.OnError
o.OnCompleted
source)
Observable.ofSeq [1;2;3] |> choose (fun _ -> failwith "qwe") |> ``should be`` 0 true false
I am having some trouble writing the tests. This actually succeeds, but it should not as the exception will flow out.
Here is how I am testing it on my own side.
open System
open System.Reactive.Linq
open FSharp.Control.Reactive
open FSharp.Control.Reactive.Observable
let choose f source =
Observable.Create (fun (o : IObserver<_>) ->
subscribeSafeWithCallbacks
(f >> Option.iter o.OnNext)
o.OnError
o.OnCompleted
source)
[<EntryPoint>]
let main argv =
use __ =
Observable.ofSeq [1;2;3]
|> choose (fun x -> failwith "qwe")
|> Observable.subscribe
(printfn "%A")
//(printfn "%A")
0
If you switch...
|> Observable.subscribe
(printfn "%A")
//(printfn "%A")
With...
|> Observable.subscribeWithError
(printfn "%A")
(printfn "%A")
Even with the current incorrect implementation, the onError
here will get fired rather than flow out. I am guessing this is why the error happens in the test. What should I do here then?
from fsharp.control.reactive.
let ``should be`` expectedNext expectedError expectedCompleted (observable:'a IObservable) =
let next = ref 0
let error = ref false
let completed = ref false
let subscription = observable |> Observable.subscribeWithCallbacks (fun _ -> incr next) (fun _ -> error := true) (fun () -> completed := true)
Assert.That(!next, Is.EqualTo expectedNext)
Assert.That(!error, Is.EqualTo expectedError)
Assert.That(!completed, Is.EqualTo expectedCompleted)
Since should be
has a fairly simple implementation, I can pick it apart a little and do the test like so...
[<Test>]
member __. ``throwing an exception in choose leads to the OnError event firing and does not lead to the exception flowing out even with a regular subscribe`` () =
let o = Observable.ofSeq [1;2;3] |> choose (fun _ -> failwith "qwe")
let error_flows_out = ref false
try o |> Observable.subscribe (printfn "%i") |> ignore
with _ -> error_flows_out := true
Assert.That(!error_flows_out, Is.EqualTo false)
o |> ``should be`` 0 true false
This should be it.
The only thing I am wondering now is why there are two versions of the tests, one for XUnit and one for NUnit. Am I expected to duplicate them here? It would be better to just erase the ones that are not being used.
from fsharp.control.reactive.
Great question about tests. The migration to Xunit was not completed. I'd love help getting those cleaned up. Or just go back to NUnit. Either is fine with me.
from fsharp.control.reactive.
Related Issues (20)
- Publish the extended Observable module HOT 1
- Add support for AsyncRx.NET
- Is there an equivalent of `concatMap`? HOT 2
- `Observable.Create` doesn't work as expected HOT 1
- Should Observable.fromEventHandler<'EventArgs> return IObservable<'EventArgs> instead of IObservable<object>? HOT 3
- Typo in the `finallyDo` description HOT 1
- F# not able to infer correct type? HOT 2
- `switchMap` does not act like `map` followed by `switch` HOT 2
- Order is not maintained in all cases of `Disposable.compose` HOT 2
- Disposable.compose mutates previous values
- Add Disposable.disposeWith function HOT 1
- Remove duplicate tests
- switchAsync and switchTask do not respect cancellation HOT 4
- Fable support HOT 3
- Consider an explicit FSharp.Core version dependency
- Make this library trimmable HOT 2
- Is Observable.fromEventGeneric constrained too much? HOT 2
- Observable.fromEventConversion have wrong generic signature
- Incompatible with System.Reactive v6? HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fsharp.control.reactive.