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());
};