This is not possible without more code to clone the strings.
Specifically, think about what happens if I run this:
let sender2 = (sender1.send)("1".to_owned());
let sender3_a = (sender2.send("2a".to_owned());
let sender3_b = (sender2.send("2b".to_owned());
At this point, both sender3_a
and sender3_b
need access to x
which is "1".to_owned()
. But since neither is borrowing from the other (they both exist completely independently), they both need to own x. Only one thing can own a variable at a time, so this can't work - you need to clone the arguments at some point, or do something else to share them.
This is also a problem for c
and b
- you are taking ownership when you pass them into sender3.send
and sender2.send
on lines 20 and 22. You effectively need to be able to pass c
into sender3.send
any number of times, but you've only created one String
. This can also be fixed by cloning things as you pass them around, if you're OK with that (and that works with your original use case, if it isn't String
s).
Lastly, if you do this, you'll be effectively borrowing all the variables rather than moving them. Rust will automatically turn this into having each closure only take borrows (for instance, then |y|
closure will only borrow x
, not move it in). We want the closures to all be independent, so they do need to move their captured variables in rather than making new borrows. The move
keyword does this.
In total, this looks like:
struct Sender<T> {
send: Box<dyn FnMut(T)>,
}
impl<T> Sender<T> {
pub fn new(send: Box<dyn FnMut(T)>) -> Self {
Sender { send }
}
}
fn main() {
let a = "1".to_owned();
let b = "2".to_owned();
let c = "3".to_owned();
let mut sender1 = Sender::<String>::new(Box::new(move |x| {
let c_clone = c.clone();
let mut sender2 = Sender::<String>::new(Box::new(move |y| {
let x_clone = x.clone();
let mut sender3 = Sender::<String>::new(Box::new(move |z| {
println!("{:?} {:?} {:?}", x_clone, y, z);
}));
(sender3.send)(c_clone.clone());
}));
(sender2.send)(b.clone());
}));
(sender1.send)(a);
}
You'll need more clones at each additional layer, as well. Here's an example with 4 layers. I've left out the _clone
suffix on the new variables to make it read better (but it's doing the exact same thing as if you had a _clone
suffix):
struct Sender<T> {
send: Box<dyn FnMut(T)>,
}
impl<T> Sender<T> {
pub fn new(send: Box<dyn FnMut(T)>) -> Self {
Sender { send }
}
}
fn main() {
let a = "1".to_owned();
let b = "2".to_owned();
let c = "3".to_owned();
let d = "4".to_owned();
let mut sender1 = Sender::<String>::new(Box::new(move |x| {
let c = c.clone();
let d = d.clone();
let mut sender2 = Sender::<String>::new(Box::new(move |y| {
let x = x.clone();
let d = d.clone();
let mut sender3 = Sender::<String>::new(Box::new(move |z| {
let x = x.clone();
let y = y.clone();
let mut sender4 = Sender::<String>::new(Box::new(move |w| {
println!("{:?} {:?} {:?} {:?}", x, y, z, w);
}));
(sender4.send)(d.clone());
}));
(sender3.send)(c.clone());
}));
(sender2.send)(b.clone());
}));
(sender1.send)(a);
}
If your actual application doesn't allow clone
ing the things returned, an alternative is wrapping everything in Arc
s. Arc
clones are cheap, and if you wrap your things in Arc
s, multiple closures can then effectively own the underlying data (at the cost of only having borrowed access to it).
Or, if you're OK with each closure only being callable once, you could use FnOnce()
rather than FnMut()
. This would fix the issue by telling rust that each closure only needs to be run once, so it's 100% fine that they move ownership of the variables around and can only be run once. (You might still need move
on some of the closures to make this compile, but that should also be fine).
Let me know if any of these work for you and your use case!