如何在另一个闭包中捕获闭包?

时间:2014-09-27 00:43:03

标签: rust

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的生命周期到期。

我怎么表达这样的话?

1 个答案:

答案 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>>(
                                                 ^~~~~~~~~~~~