今天又遇到一个新的问题,那就是在闭包函数中,无法引用闭包函数之外的变量。
fn main() {
let cfg = config::cfg::get_config();
let filename = cfg.las.as_ref().unwrap().access_log.as_ref().unwrap();
// println!("{}",filename);
// let mut p = poly::Poly::new();
let mut s = String::from("_");
let mut log_watcher = LogWatcher::register(filename.to_string()).unwrap();
log_watcher.watch(|line: String| {
let (_, token) = parse::lex::parser(&line);
// p.push(LineStat {});
print!("{}", s);
process::report::send(token);
});
}
上面代码中,watch
传入参数为一个闭包函数,其中需要引用main
函数中的局部变量s
,但是会报错
error[E0308]: mismatched types
--> src/main.rs:22:23
|
22 | log_watcher.watch(|line: String| {
| _______________________^
23 | | let (_, token) = parse::lex::parser(&line);
24 | | // p.push(LineStat {});
25 | | print!("{}", s);
26 | | process::report::send(token);
27 | | });
| |_____^ expected fn pointer, found closure
|
= note: expected fn pointer `fn(std::string::String)`
found closure `[closure@src/main.rs:22:23: 27:6]`
note: closures can only be coerced to `fn` types if they do not capture any variables
查看logwatcher
源码,watch
该版本(0.1.0)方法定义如下
pub fn watch(&mut self, callback: fn (line: String)) {
....
}
不过我后来发现logwatcher
版本升级到(0.1.1)之后,该方法变为
pub fn watch<F: ?Sized>(&mut self, callback: &mut F)
where
F: FnMut(String) -> LogWatcherAction,
{
....
}
如此可以正常调用,代码如下
fn main() {
let cfg = config::cfg::get_config();
let filename = cfg.las.as_ref().unwrap().access_log.as_ref().unwrap();
let mut watcher = LogWatcher::register(filename.to_string()).unwrap();
let mut poly: Poly = Poly::new();
watcher.watch(&mut |line: String| {
poly.clone().push(line);
LogWatcherAction::None
})
}
由此可见,闭包与函数还是有区别的。但是回调函数定义为Fn/FnMut类型就可以同时接受闭包和函数类型的回调参数。举例如下
let a = String::from("abc");
let mut x = || println!("x {}", a);
fn y() {
println!("y")
}
fn wrap(c: &mut Fn()) {
c()
}
wrap(&mut x); // pass a closure
wrap(&mut y); // pass a function
同样可以参考 stackoverflow 的这个提问。