Hi,
I'm working my way through the Rust book and have been playing with the chapter 16.2 concurrency examples. I made a small modification to the listing 16.10 and get compilation errors, but I cannot see why.
I put and endless loop around the "for val in vals" loop and it then complains about vals, move and not implementing the Copy trait. Despite Rust's error reporting being generally very good, I'm struggling to figure out this one and understand what the problem is. Here's my code (slightly modified 16.10 example):
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let vals = vec![
String::from("hi"),
String::from("from"),
String::from("the"),
String::from("thread"),
];
loop { // <--------- My added line
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
} // <--------- My added line
}
});
for received in rx {
println!("Got: {}", received);
}
}
If I either remove my loop{}, or comment out the tx.send line then it compiles.
Can someone explain to me how adding the loop causes a problem?
In the first iteration of the loop, everything is fine.
However, in the second iteration (and forward), we try to move out of vals because of the for loop - but it was already moved in the previous iteration.
Could you show the code that compiles in this case? I tried to comment it out myself and got the same error, since the problematic code wasn't changed.
Ah, ok. So by iterating through it once means I cannot access it again in the same context? So this produces the same error (enclosing loop also removed):
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
}
println!("{:?}", vals);
So assuming I had a situation where I wanted to access it more than once within the same scope.
If I simplify the code, getting rid of all the example threading stuff to:
fn main() {
let vals = vec![
String::from("this"),
String::from("is"),
String::from("a"),
String::from("test"),
];
for val in vals {
// do something arbitrary
println!("{}", val);
}
println!("{:?}", vals);
}
then the same problem is encountered on the final line. I think I understand now that the loop moves the vector vals into the interator val and so is "gone" afterwards.
How would I borrow the vector for the iterator instead? (I must admit, the intricacies of the borrowing model is my biggest hurdle getting to grips with the language. All the examples and all the courses make sense, until I try to apply it myself.. But I'm sure I'll get there!)
Ah yes, thanks. That makes complete sense. I'd actually tried that earlier but I think for some reason it was still throwing the error, like perhaps the rust-analyzer was using cached data.
I found this also works:
for val in 0..vals.len() {
// do something arbitrary
println!("{}", vals[val]);
}
println!("{:?}", vals);