我正试图让我的头围绕Rust.我的alpha版本为1.
这是我正在尝试编程的问题:我有一个浮动向量.我想异步设置一些线程.每个线程都应该等待向量的每个元素指定的秒数,并返回元素的值加上10.结果需要按输入顺序排列.
当然,这是一个人为的例子,但我想看看我是否可以在转向更复杂的代码之前实现一些简单的东西.到目前为止,这是我的代码:
use std::thread;
use std::old_io::timer;
use std::time::duration::Duration;
fn main() {
let mut vin = vec![1.4f64, 1.2f64, 1.5f64];
let mut guards: Vec<thread::scoped> = Vec::with_capacity(3);
let mut answers: Vec<f64> = Vec::with_capacity(3);
for i in 0..3 {
guards[i] = thread::scoped( move || {
let ms = (1000.0f64 * vin[i]) as i64;
let d = Duration::milliseconds(ms);
timer::sleep(d);
println!("Waited {}", vin[i]);
answers[i] = 10.0f64 + (vin[i] as f64);
})};
for i in 0..3 {guards[i].join(); };
for i in 0..3 {println!("{}", vin[i]); }
}
Run Code Online (Sandbox Code Playgroud)
所以输入向量是[1.4, 1.2, 1.5],我期待输出向量[11.4, 11.2, 11.5].
我的代码似乎有很多问题,但第一个是我收到编译错误:
threads.rs:7:25: 7:39 error: use of undeclared type name `thread::scoped`
threads.rs:7 let mut guards: Vec<thread::scoped> = Vec::with_capacity(3);
^~~~~~~~~~~~~~
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
似乎还存在许多其他问题,包括vin在闭包内使用.此外,我不知道是什么move,除了我见过的每个例子似乎都使用它的事实.
您的错误是由于thread::scoped函数而不是类型.你想要的是函数的结果类型Vec<T>在哪里T.Rust有一个简洁的功能可以帮助您:在许多情况下,它会自动检测变量的正确类型.如果你使用
let mut guards = Vec::with_capacity(3);
Run Code Online (Sandbox Code Playgroud)
guards您.push()第一次使用时将选择的类型.
似乎还有许多其他问题.
你正在guards[i]第一个for循环中访问,但是guards向量的长度是0.它的容量是3,这意味着只要向量永远不包含3个以上的元素,就不会有任何不必要的分配.用guards.push(x)而不是guards[i] = x.
thread::scoped期望a Fn() -> T,所以你的闭包可以返回一个对象.你打电话时得到那个对象.join(),所以你不需要答案矢量.
vin被移到封闭处.因此,在创建警卫的循环的第二次迭代中,vin不再可用于移动到"第二"闭包.每次循环迭代都会创建一个新的闭包.
i被移到封闭处.我不知道那里发生了什么.但解决方案是let inval = vin[i];在闭包之外,然后inval在闭合内部使用.这也解决了第3点.
vin是可变的.但你永远不会改变它.如果您不需要,不要可变地绑定变量.
vin是一个数组f64.因此(vin[i] as f64)什么都不做.因此,您可以直接使用vin[i].
join走出警戒.由于您无法移出数组,因此无法将索引编入索引数组并在指定索引处连接该元素.你可以做的是遍历数组的元素并加入每个守卫.
基本上这意味着:不要遍历indices(for i in 1..3),而是for element in vector尽可能迭代元素().
所有上述实施:
use std::thread;
use std::old_io::timer;
use std::time::duration::Duration;
fn main() {
let vin = vec![1.4f64, 1.2f64, 1.5f64];
let mut guards = Vec::with_capacity(3);
for inval in vin {
guards.push(thread::scoped( move || {
let ms = (1000.0f64 * inval) as i64;
let d = Duration::milliseconds(ms);
timer::sleep(d);
println!("Waited {}", inval);
10.0f64 + inval
}));
}
for guard in guards {
let answer = guard.join();
println!("{}", answer);
};
}
Run Code Online (Sandbox Code Playgroud)