您的代码正在使用“盒装”闭包。这些闭包通过引用捕获值,因此捕获的值必须比闭包更长寿。您正在尝试捕获b,这是一个参数,因此它的生命周期是函数调用的持续时间。你不能用“盒装闭包”做你想做的事。
未装箱的闭包已添加到语言中以解决此类问题。以下是 map_one 的定义方式:
#![feature(overloaded_calls, unboxed_closures, unboxed_closure_sugar)]
type Time = f32;
fn map_one<'a, T, R, F: Fn<(T,), R>, B: Fn<(Time,), T>>(
f: F, b: B) -> Box<Fn<(Time,), R>+'a> {
box |&: time| -> R {
f(b(time))
}
}
Fn 是一个带有call 方法的特征,该方法通过不可变引用获取self(FnMut 通过可变引用获取self,FnOnce 通过值获取self)。捕获的值被移动到闭包中,而不是被引用。
输入闭包参数使用实现Fn trait 的类型参数定义,这是按值传递闭包的唯一方法。但是,返回值必须装箱,因为具体的结果类型(实现Fn)是由编译器创建的,我们无法命名。
我尝试编写使用map_one 的main,但是I'm getting an internal compiler error... 那时,我无法判断我是否犯了错误,或者代码是否应该有效。 (这些 Rust 问题可能与此错误有关:#16672、#16791、#17060。)
fn main() {
let t = 30f32;
let fa = |&: a: String| -> uint { a.len() };
let fb = |&: b: f32| -> String { b.to_string() };
let m = map_one(fa, fb);
let r = m.call((t,));
println!("{}", r);
}
注意:我无法使用您的 Behaviour 泛型类型别名来绑定 B。
#![feature(overloaded_calls, unboxed_closures, unboxed_closure_sugar)]
type Time = f32;
type Behaviour<T> = Fn<(Time,), T>;
fn map_one<'a, T, R, F: Fn<(T,), R>, B: Behaviour<T>>(
f: F, b: B) -> Box<Behaviour<R>+'a> {
box |&: time| -> R {
f(b(time))
}
}
编译器抱怨:
<anon>:6:41: 6:53 error: `Behaviour` is not a trait
<anon>:6 fn map_one<'a, T, R, F: Fn<(T,), R>, B: Behaviour<T>>(
^~~~~~~~~~~~
<anon>:6:41: 6:53 note: `type` aliases cannot be used for traits
<anon>:6 fn map_one<'a, T, R, F: Fn<(T,), R>, B: Behaviour<T>>(
^~~~~~~~~~~~