Comments (8)
Thanks for the question, and this is indeed possible! You can create new futures with combinators with functions like map
and then
which run more computations once a future has completed.
In this way you can "attach callbacks" by transforming the underlying future. It's a little different from exactly what you'll see in Guava and Akka I believe, but it all achieves the same goal!
Let me know if that's not what you were thinking, though.
from futures-rs.
Unfortunately not.
Attaching a callback is not the same as composing futures.
Thanks anyway, will have to look at some other lib.
from futures-rs.
Attaching a callback is not the same as composing futures.
What's the difference that makes this crate a deal-breaker? I'm curious.
from futures-rs.
@norru, to be clear, you should be able to do something like:
fn on_complete<A, F>(a: A, f: F) -> Box<Future<Item=A::Item, Error=A::Error>>
where A: Future,
F: FnOnce(&A::Item) + 'static,
{
Box::new(a.map(|x| {
f(&x);
x
}))
}
That way you can register "completion callbacks" and similarly error callbacks if necessary.
from futures-rs.
(deleted comment, Gmail broke my Markdown, see below)
from futures-rs.
Fair enough! It looks like the discussion is far from over and I might have sounded a bit too dismissive to begin with. Apologies for that! :)
TL;DR this pattern built on ".map()" doesn't work for me but maybe we're getting somewhere.
I haven't tried yet but there may be a limitation to what I want to do WRT "fire and forget" as Rust's scoping rules may forbid patterns I'm used to in other languages/environments anyway so basically I'm not bound by the library but by the language itself. I need to try that as my Rust-fu is not that good. For instance, if I do:
let c = on_complete(...)
What happens when c
goes out of scope?
Anyway, here's a bunch of things that I would expect when registering a callback, as I'm kind of used to:
- Callbacks are only be used for side effects - typically sending "fire or forget" messages or, say, logging.
- Callbacks cannot cause the future to fail or alter its result
- Multiple callbacks can be attached independently to the same future. If I pass a future to multiple subsystems, even concurrently, each system can register its own interest to the result independently.
- Order of execution of callbacks doesn't matter in the general case (but I've used mechanisms that make it possible)
Here's a completely made up example of a thing I'm expecting to be able to do. Excuse the "pseudo-Rust".
fn main() {
a = <some future>
...
b = a.map(|x| { ... })
...
do_all(a, b)
...keep doing stuff...
}
...
fn do_all(a, b) {
...
proc1(a, b)
proc2(a, b)
...
}
fn proc1(a, b) {
...
on_callback(a, |x| { ..write x to file "A" })
...
}
fn proc2(a, b) {
...
on_callback(b, |x| { ..send message x...})
...
}
This allows main to fire some computations, one depending on the other, and pass both results down the line without having to care about what is interested in what, and without the two subsystems caring whether a or b are dependent from each other.
If you were to ask "why would you want to do that" the answer would be "because". I already do that somewhere else: it works, it's efficient, it's easy, it's compact, it's maintainable, and it's "reasonably safe" in the right context. But, again, I may be missing something related to the Rust-ness of the thing and I wouldn't be looking at Rust if I were 100% happy with what I've got.
from futures-rs.
One part about this crate is that it's intended to be maximally flexible not necessarily locking you into any particular paradigm or pattern. That's done through having futures as a trait rather than a type. That way you can implement whatever semantics you'd like.
With that in mind it's also worth pointing out that today while there's no exact analog for "attach a list of callbacks to get run on completion" it can certainly be done with a custom trait implementation! So while this can be emulated via map
, you could also imagine a custom adapter which implements this paradigm.
Finally, ownership in Rust means that many exact patterns in other languages don't translate well. For example a future with this library can never be concurrently referenced because all the methods take &mut self
. A handle could be concurrently referenced, which again the trait allows for, but a future itself wouldn't be. Additionally by tracking ownership of a future we're able to precisely know who's got access to that and track it over time as well.
For example in the snippet you gave this would be illegal in Rust:
proc1(a, b)
proc2(a, b)
as that would move a
and b
with the first procedure, disallowing access with the next. You could pass around &mut a
and &mut b
, however, and use a custom adapter to register callbacks, though, and it'd solve your problem I believe.
Does that all make sense? Would be more than willing to clarify anything if needed!
from futures-rs.
Yep, that's illegal, but, as I clearly stated, it's not Rust either.
I just didn't want to start down the rabbit hole of borrowage so I went through the easier "pseudo-Rust" way to explain what my intent was.
I can also imagine lots of adapters and also implementing my own futures - but that is the kind of common things that I would expect a good Futures library to solve for me, so I don't have to reinvent the wheel. Attaching a callback is a very common pattern.
Any sufficiently flexible library is indistinguishable from no library at all ;)
By the way, in the other Futures libraries that I know and use (caveat: not on Rust!), callbacks are a powerful primitive on which I build my own abstractions. I do also use composition with great effects (or at least get the job done). I know of libraries which don't implement callbacks as primitives (on which you can bolt-on a half-assed implementation of those if you hammer them hard enough) and that's a reason good enough to avoid them altogether.
from futures-rs.
Related Issues (20)
- Analogue of .last() method
- parse error in `select!`/`select_biased!` macro HOT 2
- Error on OSX by futures-executir HOT 1
- Consider removing ArcWake, re-export std::task::Wake HOT 3
- Fine-tune the Ordering for num_senders
- Feature Request: make FuturesUnordered splitable.
- `FuturesUnordered` guaranties
- Unbounded memory use of `futures::channel::mpsc` with `SinkExt::feed`
- Question: futures-rs::channels implement Send trait HOT 1
- Non-send future produced by chaining `Stream` combinators HOT 1
- Behavior of any() / all() / try_any() / try_all() is not documented for empty stream
- Feature request: add `StreamExt::eq` like `Iterator::eq`
- Reusing `AbortRegistration`
- ConcurrentStream usage with tokio leads to ACCESS_VIOLATION HOT 3
- [Discussion] `Shared` seems to wake up the same waker that was polling it HOT 1
- Add `StreamExt::map_while`
- io: impl AsyncWrite for Empty
- Stream & Sink Error types could benefit from core::fmt::Debug bound HOT 1
- implement OwnedMappedMutexGuard
- `StreamExt::scan` lacks a non-Option version
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 futures-rs.