Я получаю ошибку, что я перемещаю (а) значения, которых я не должен быть, но ошибка не дает понять, что я случайно перемещаю, и я пропускаю это, когда я просто посмотрите на код.Где незаконный ход в моем коде?
Ошибка:
-*- mode: compilation; default-directory: "~/Developer/Rust/optimal_subset_finder/src/" -*-
Compilation started at Thu Aug 27 21:53:26
cargo build
Compiling optimal_subset_finder v0.1.1 (file:///Users/camdennarzt/Developer/Rust/optimal_subset_finder)
main.rs:66:23: 98:10 error: cannot move out of captured outer variable in an `FnMut` closure
main.rs:66 thread::spawn(move || {
main.rs:67 let mut best_set : Vec<String> = Vec::new();
main.rs:68 let mut best_count = 0;
main.rs:69 let mut rng = thread_rng();
main.rs:70 let mut indices = Vec::new();
main.rs:71 let limit = attempts.clone()/num_cpus::get();
...
note: in expansion of closure expansion
main.rs:66:23: 98:10 note: expansion site
note: in expansion of closure expansion
main.rs:63:57: 99:6 note: expansion site
main.rs:66:23: 98:10 error: cannot move out of captured outer variable in an `FnMut` closure
main.rs:66 thread::spawn(move || {
main.rs:67 let mut best_set : Vec<String> = Vec::new();
main.rs:68 let mut best_count = 0;
main.rs:69 let mut rng = thread_rng();
main.rs:70 let mut indices = Vec::new();
main.rs:71 let limit = attempts.clone()/num_cpus::get();
...
note: in expansion of closure expansion
main.rs:66:23: 98:10 note: expansion site
note: in expansion of closure expansion
main.rs:63:57: 99:6 note: expansion site
error: aborting due to 2 previous errors
Could not compile `optimal_subset_finder`.
To learn more, run the command again with --verbose.
Compilation exited abnormally with code 101 at Thu Aug 27 21:53:27
код:
extern crate rand;
extern crate csv;
extern crate num_cpus;
extern crate rustc_serialize;
extern crate docopt;
use std::fs::File;
use csv::Reader;
use rand::{thread_rng, sample};
use std::thread;
use std::io::{self, Write};
use std::sync::{Arc, Mutex};
use docopt::Docopt;
use std::collections::HashSet;
fn as_bool(rdr:&mut Reader<File>)->Vec<Vec<bool>>{
rdr.records().map(|r|{
r.unwrap().iter().skip(1).map(|r|{
r == "TRUE"
}).collect()
}).collect()
}
fn as_strings(rdr:&mut Reader<File>)->Vec<String>{
rdr.records().map(|r|{
r.unwrap()[0].clone()
}).collect()
}
fn met_n_in_common(n:usize,csv:&Vec<Vec<bool>>)->bool{
csv.iter().all(|r|r[n])
}
fn mets_in_common(csv:&Vec<Vec<bool>>)->usize {
(0..csv[0].len()).filter(|i| met_n_in_common(*i,csv)).count()
}
const USAGE: &'static str = "
Usage:
./optimal_subset_finder PATH ATTEMPTS
";
#[derive(Debug, RustcDecodable)]
struct Args {
arg_PATH: String,
arg_ATTEMPTS: usize,
}
fn main() {
let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
let attempts = args.arg_ATTEMPTS.clone();
let mut csv = csv::Reader::from_file(args.arg_PATH.clone()).unwrap();
let data = as_bool(&mut csv);
csv.seek(0);
let files = as_strings(&mut csv);
let tried_indices = Arc::new(Mutex::new(HashSet::new()));
let results = Arc::new(Mutex::new(Vec::new()));
let mut threads : Vec<_> = (0..num_cpus::get()).map(|i|{
let tried_indices = tried_indices.clone();
let results = results.clone();
thread::spawn(move || {
let mut best_set : Vec<String> = Vec::new();
let mut best_count = 0;
let mut rng = thread_rng();
let mut indices = Vec::new();
let limit = attempts.clone()/num_cpus::get();
for _ in (0..limit) {
{
let mut tried_indices = tried_indices.lock().unwrap();
while {
let count = *sample(&mut rng, 13..83, 1).first().unwrap();
indices = sample(&mut rng, 0..83, count);
tried_indices.contains(&indices)
}{}
tried_indices.insert(indices.to_owned());
};
let current_set:Vec<_> = {
indices.iter().map(|i|{
files[*i].clone()
}).collect()
};
let current_count = mets_in_common(&data);
if (current_count > best_count){
best_count = current_count;
best_set = current_set;
}
}
{
let mut results = results.lock().unwrap();
results.push((best_count,best_set));
}
})
}).collect();
for t in threads.into_iter() {
t.join();
}
{
let mut results = results.lock().unwrap().to_owned();
let first = results.pop().unwrap();
let (count,set) = results.into_iter().fold(first,|a,r| if(a.0 < r.0){r}else{a});
println!("results {:?} {:?}",count,set);
}
}
Попробуйте добавить формулировки формы 'let x = & x' (или' let x = & mut x', если вам нужна изменчивость) перед вызовом 'thread :: spawn', где' x' - это переменная, используемая в закрытие было передано 'thread :: spawn'. При этом закрытие будет захватывать ссылки, а не значения напрямую. –
Тогда компилятор не знает, что ссылки живут достаточно долго, потому что область действия на карте заканчивается до того, как поток будет выполнен. –