我编写了一个程序来访问基于的目录 关于此page的示例。
编译时,编译显示以下'note':
由于在关闭时使用,此前借用file_counter
;
如何显示file_counter的值?
在此程序中,是否有更好的(即更像功能)方法来计算显示的文件, 也许是一个不可变的变量和/或递归?
非常感谢。
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))
}
}
答案 0 :(得分:0)
你可以通过轻微的重组来解决这个问题,将关闭置于一个内部块中:
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)
};
}
至于它为什么会发生,这是因为闭包通过唯一引用(在你的情况下是可变的)捕获它的所有环境,好像它被声明为这样(假装关闭时刻按值捕获它们的环境;实际上这是unboxed闭包的工作方式):
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());
};
因此file_counter_ref
引用持续到定义闭包的块的末尾。在您的情况下,它是从闭包声明开始的整个main
函数。我同意,这可能是令人惊讶的,我当然也会认为闭包环境借助于闭包(例如当闭包被移入函数并且此函数返回时),但这就是现在的情况。
Rust中闭包的情况目前还不稳定:刚刚将未装箱的闭包添加到语言中,因此旧的盒装闭包(如本例中的闭包)很快就会消失;此外,借阅检查器是also being improved。这些功能可能会以复杂的方式进行交互,因此您的原始示例很快就会成为可能:)(当然只是推测)