Rust 处理闭包中的可变计数器变量
我写了一个程序来访问基于 关于这个例子 当我编译它时,编译器会显示以下“注意事项”: 由于在闭包中使用,Rust 处理闭包中的可变计数器变量,rust,Rust,我写了一个程序来访问基于 关于这个例子 当我编译它时,编译器会显示以下“注意事项”: 由于在闭包中使用,文件\u计数器的先前借用发生在此处 如何显示文件计数器的值 在这个程序中,是否有更好的(即更像功能)方式来计算显示的文件数, 可能是不可变变量和/或递归 非常感谢 fn main() { let mut file_counter = 0i; let display_path_closure = |path: &Path| { file_count
文件\u计数器
的先前借用发生在此处
如何显示文件计数器的值
在这个程序中,是否有更好的(即更像功能)方式来计算显示的文件数,
可能是不可变变量和/或递归
非常感谢
fn main() {
let mut file_counter = 0i;
let display_path_closure = |path: &Path| {
file_counter += 1;
println!("{}) path = {}", file_counter, path.display());
};
let path = Path::new("z:/abc");
let _ = match visit_dirs(&path, display_path_closure) {
Err(e) => println!("error: {}", e),
Ok(_) => println!("Counter: {}", file_counter)
};
}
fn visit_dirs(dir: &Path, cb: |&Path|) -> io::IoResult<()> {
if dir.is_dir() {
let contents = try!(fs::readdir(dir));
for entry in contents.iter() {
if entry.is_dir() {
try!(visit_dirs(entry, |p| cb(p)));
} else {
cb(entry);
}
}
Ok(())
} else {
Err(io::standard_error(io::InvalidInput))
}
}
fn main(){
让mut file_counter=0i;
让显示_path_closure=|path:&path|{
文件_计数器+=1;
println!(“{})path={}”,文件\计数器,path.display();
};
让path=path::new(“z:/abc”);
让u=匹配访问目录(&path,display\u path\u closure){
Err(e)=>println!(“错误:{}”,e),
Ok()=>println!(“计数器:{}”,文件计数器)
};
}
fn访问目录(目录:&Path,cb:&Path)->io::IoResult{
if dir.is_dir(){
让contents=try!(fs::readdir(dir));
用于contents.iter()中的条目{
if entry.is_dir(){
试试看!(访问目录(条目,| p | cb(p));
}否则{
cb(录入);
}
}
好(())
}否则{
错误(io::标准_错误(io::无效输入))
}
}
您可以通过稍微重新构造,将闭包放入内部块中来解决此问题:
fn main() {
let path = Path::new("z:/abc");
let mut file_counter = 0i;
let result = {
let display_path_closure = |path: &Path| {
file_counter += 1;
println!("{}) path = {}", file_counter, path.display());
};
visit_dirs(&path, display_path_closure)
};
let _ = match result {
Err(e) => println!("error: {}", e),
Ok(_) => println!("Counter: {}", file_counter)
};
}
至于为什么会发生这种情况,这是因为闭包通过唯一引用捕获其所有环境(在您的情况下是可变的),就好像它是这样声明的(暂时假装闭包通过值捕获其环境;事实上,这就是未绑定闭包的工作方式):
因此file\u counter\u ref
引用持续到定义闭包的块的末尾。在您的例子中,它是从闭包声明开始的整个main
函数。我同意,这可能会让人惊讶,我当然也会认为闭包环境会随着闭包而消亡(例如,当闭包被移动到函数中并且这个函数返回时),但现在情况就是这样
Rust中闭包的情况目前是不稳定的:unbox闭包刚刚被添加到语言中,所以旧的box闭包(如本例中的闭包)很快就会消失;此外,借用检查器也很重要。这些特性可能以复杂的方式相互作用,因此您最初的示例可能很快就会成为可能:)(当然,这只是猜测)
let mut file_counter = 0i;
let file_counter_ref = &mut file_counter;
// file_counter_ref is a plain pointer so it is copied into the closure,
// not taken by reference itself
let display_path_closure = |path: &Path| {
*file_counter_ref += 1;
println!("{}) path = {}", *file_counter_ref, path.display());
};