有没有办法有盒装和副移动闭包?

时间:2015-02-21 12:09:35

标签: closures rust

我需要一个捕获按值的闭包并且最多被调用一次,但是我不能在每个传递的闭包上使用闭包单态,因为闭包和函数是相互递归的,并且单态化阶段失败。我试过像:

fn closure_user(closure: Box<FnOnce(usize) -> bool>) -> bool {
    closure(3)
}

fn main() {
    let big_data = vec![1, 2, 3, 4];
    closure_user(Box::new(|x| {
        let _ = big_data.into_iter();
        false
    }));
}
error[E0161]: cannot move a value of type dyn std::ops::FnOnce(usize) -> bool: the size of dyn std::ops::FnOnce(usize) -> bool cannot be statically determined
 --> src/main.rs:2:5
  |
2 |     closure(3)
  |     ^^^^^^^

未装箱的版本是:

fn closure_user<F>(closure: F) -> bool
where
    F: FnOnce(usize) -> bool,
{
    closure(42)
}

fn main() {
    let big_data = vec![1, 2, 3, 4];
    closure_user(|x| {
        let _ = big_data.into_iter();
        false
    });
}

似乎无法将闭包装箱和取消装箱作为FnOnce特征对象。有没有办法让盒装(没有类型参数)和副移动(只有一个调用)闭包?

2 个答案:

答案 0 :(得分:3)

这是可能的,但现在你必须通过不稳定的std::thunk::Thunk

来做到这一点
use std::thunk::{Invoke, Thunk};

fn closure_user(closure: Thunk<usize, bool>) -> bool {
    closure.invoke(3)
}

fn main() {
    let big_data = vec![1, 2, 3, 4];
    closure_user(Thunk::with_arg(|x| {
        let _ = big_data.into_iter();
        false
    }));
}

这是由于当前类型系统的限制 - 无法从特征对象中移出 - 应该尽快解决。有关详细信息,请参阅博文Purging Proc

答案 1 :(得分:1)

从Rust 1.35开始,现在可以使用您的原始语法:

manage.py migrate