type Time = f32;
type Behaviour<'a,T> = |Time|: 'a -> T;
fn map_one<'a,T,R>(f: |T| -> R
,b: Behaviour<'a,T>)
-> Behaviour<'a,R>{
|time| -> R {
f(b(time))
}
}
错误:
<anon>:8:9: 8:10 error: captured variable `b` does not outlive the enclosing closure
<anon>:8 f(b(time))
^
<anon>:6:38: 10:2 note: captured variable is valid for the block at 6:37
<anon>:6 -> Behaviour<'a,R>{
<anon>:7 |time| -> R {
<anon>:8 f(b(time))
<anon>:9 }
<anon>:10 }
我认为错误意味着当我尝试将b
移动到另一个闭包中时,&#39; a的生命周期到期。
我怎么表达这样的话?
答案 0 :(得分:1)
您的代码正在使用&#34;盒装&#34;关闭。这些闭包通过引用捕获值,因此捕获的值必须比闭包更长寿。您正在尝试捕获b
,这是一个参数,因此其生命周期是函数调用的持续时间。你不能做你想做的&#34;盒装封闭。
语言中添加了未装箱的闭包以解决此类问题。以下是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
特征的类型参数定义的,这是通过值传递闭包的唯一方法。但是,返回值必须加框,因为具体的结果类型(实现Fn
)是由编译器创建的,我们无法为其命名。
我尝试写main
使用map_one
,但是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>>(
^~~~~~~~~~~~