The map
method is for lifting a single Signal.
If you want to lift multiple Signals (which is equivalent to CombineLatest
in Rx), you can use map_ref
:
map_ref! {
let a = foo.some_method(),
let b = bar.some_other_method(),
let c = qux.last_method() => {
*a + *b + *c
}
}
You don't need to keep quoting Rx. I know it.
There's already dozens of operators for Futures/Streams/Signals, and more are being added all the time: StreamExt
, TryStreamExt
, FutureExt
, TryFutureExt
, SignalExt
, SignalVecExt
If your favorite combinator isn't available yet, you're welcome to implement it yourself and send a pull request. Everything is open source, and created by volunteers.
For debounce specifically, you can use debounce with Streams and Signals. Rx Observable is like a mishmash of Stream + Signal, so everything you can do with Rx you can do with Streams / Signals.
This is misunderstanding how the system works. You can have parallel Futures / Streams / Signals which all run on the same Executor. In fact, you'll usually have only one Executor per program.
You can think of the Executor as being like a thread pool which randomly assigns Futures / Streams / Signals to different threads.
There is no copying, because op2()
will consume op1()
, so it has exclusive access to it. And so Rust's compiler is happy, the Rust memory model is happy, and everything has 0 cost.
If you want to split a Stream/Signal so it has multiple consumers, you can of course do that, but now you have to use something like a Broadcaster
(which internally uses an Arc<Mutex<Vec<Weak<BroadcasterStatus>>>>
).
The key thing is that most of the time you only need to split the roots, not intermediate Streams / Signals, so you only pay the performance cost for splitting when you need it.
That means you only have 1 allocation for each root, which is far more efficient than multiple allocations per node (which is what you would get with Rx's model).
It's out of date, but this general principle is explained well here.
I'm not sure why you're doubting whether it exists or not: Futures / Streams / Signals have existed for years, and have been used in real programs for years.
The Future / Stream code is here, and the Signals code in here.
Though if you really didn't want to reinvent the wheel, the best thing would be to contribute to the already large ecosystem, rather than inventing a new system.
There seems to be multiple misunderstandings here. First, stack allocated things can be passed between threads.
Second, any sort of Stream/Signals/Observable/whatever system isn't going to be stack allocated. Instead, all the data will live inside structs, and those structs will ideally be allocated exactly once (on the heap). That's exactly what happens with Futures/Streams/Signals.
Third, Futures/Streams/Signals can run on different threads simultaneously and communicate with each other (using Rust's standard multi-threading tools). If they couldn't, then they would be a lot less useful.