No, there isn't a way to do this. One reason for this is because you can't efficiently make a Sender<B>, because you would need to type erase the Fn(B) -> A. You can make a combinator like so,
The only way here is to create fresh new (Sender<B>, Receiver<B>) pair, spawn a new thread, and pipe the Receiver<B> to the Sender<A> via impl Fn(B) -> A, and use the Sender<B> you've made.
For me, I'll use neither Sender<B> nor Rc<dyn Fn(B)> but create a new struct that wraps over Sender<A> and generic F: Fn(B) -> A. No more allocation, no dyn, easier to reasoning, more performant (may not be significant), and more Rusty(personally).
I never mentioned this as a requirement in my original post, but I think there is a key difference between your playground post and a Rc<dyn Fn(B)>.
I have the following weird situation:
crate Foo:
has some function that generates B's
and wants to send/callback on these B's
imports struct B;
does NOT import struct A;
crate X:
imports A, B;
has function F;
calls function from crate Foo
If I am understanding the Playground example correctly, it seems that the location that generates the B's, needs to construct a Map<...>, which implies it needs to import A -- is that correct?
Again, I never mentioned this as part of the original post.
Oh, I see what you mean! Sorry, I misunderstood what you were asking. In this case you can depend on the SenderExt trait instead of Sender or Map, either through generics or by dynamic dispatch.
crate foo:
some_func(callback: impl Sender<B>) {
... blah blah ...
let b: B = ...;
callback.send(b);
...
}
Yes, it will generate 2 instances. You can use dynamic dispatch to get around this to an extent, but you will have to specify the error type generically. This means that it will still generate 2 instances in your case. If you don't want that, then you will need to create a new trait that ignores the error type.