Recently, I'm implementing ReactiveX Extensions by Rust, named rx_rs. And now it can do some easy work now. I'm confusing in which is a better way to provide error handling API.
For a simple example:
let numbers = Subject::new();
let odd = numbers.clone().map(|i| {
// in this closure, you may want throw an error.
}).subscribe(
|v| println!("{} ", *v),
|ec: &ErrComplete<()>| {
// process Error or Complete here.
})
numbers.next(1);
In operator like map, some error may occur, and user want to throw an exception, and will be processed by error callback registered in subscribe. There are two ways in my mind right now.
First way, just panic
...
let odd = numbers.clone().map(|i| {
// some logic code ...
panic!("Network occur!");
}) ...
In this way, this panic will be captured by panic::catch_unwind, and the error handling closure will be called.
Second way, every operator should return a Result type.
let odd = numbers.clone().map(|i| {
// some logic code ...
Err("Network occur!");
}) ...
In this way, when an operator return a Err, error handling closure for this stream will be call. It's maybe boring, every operator returned type will be wrapped with Result. Like a filter operator never return an error, must be return Ok(bool), can't direct return bool. And how if the operator return type really is an error type, not because an error occur ? Will be confused, must return OK(Err(_)).
So, does panic::catch_unwind is the right way, or anyone has any ideas about it?
You should note that panic!() does not always unwind. If the binary is compiled with panic = abort flag, panic!() aborts the whole process and catch_unwind become meaningless.
Rule of thumb is: do not use panic!() for error handling.
Propagating runtime errors (such as network errors) via Result is the right way.
panic!() is supposed to be only for signalling bugs that the programmer has to fix (things that documentation says are not allowed, but the program did them anyway, such as reading index out of bounds).
surprise, I also do something similar 2 week ago rxrust, it has a little bit more extensions like fold, flat_map, schedulers, basically work but lack of documents, if you interested in.
your error issue is something a flat map works for, just flat an error observable, so I'm not sure why extension isn't important in this case
it could be done like
Nice, I'll learn your code later. It's important, but at this moment is a very early period for rx_rs. It's more important to define an easy use api, and provide an almost zero cost abstractions.