【问题标题】:How do I capture a closure in another closure?如何在另一个闭包中捕获一个闭包?
【发布时间】:2014-09-27 00:43:02
【问题描述】:
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 移动到另一个闭包时,'a 的生命周期已到期。

我该如何表达这样的事情?

【问题讨论】:

标签: rust


【解决方案1】:

您的代码正在使用“盒装”闭包。这些闭包通过引用捕获值,因此捕获的值必须比闭包更长寿。您正在尝试捕获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 方法的特征,该方法通过不可变引用获取selfFnMut 通过可变引用获取selfFnOnce 通过值获取self)。捕获的值被移动到闭包中,而不是被引用。

输入闭包参数使用实现Fn trait 的类型参数定义,这是按值传递闭包的唯一方法。但是,返回值必须装箱,因为具体的结果类型(实现Fn)是由编译器创建的,我们无法命名。

我尝试编写使用map_onemain,但是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>>(
                                                 ^~~~~~~~~~~~

【讨论】:

  • 对于#[feature(unboxed_closure_sugar)],您可以将|&amp;:...| -&gt; ... 用于Fn&lt;(...), ...&gt;。我还建议使用|&amp;mut:...| -&gt; ...(和FnMut&lt;(...), ...&gt;,相应地),因为它更通用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多