如何克隆闭包,以便它们的类型相同?

时间:2016-10-01 05:07:55

标签: rust closures

我有一个看起来像这样的结构:

pub struct MyStruct<F> where F: Fn(usize) -> f64 {
    field: usize,
    mapper: F,
    // fields omitted
}

如何为此结构实现Clone

我发现可以复制函数体的一种方法是:

let mapper = |x| (mystruct.mapper)(x);

但这导致mapper的类型与mystruct.mapper的类型不同。

playpen link

4 个答案:

答案 0 :(得分:3)

你不能Clone关闭。能够为闭包实现Clone的唯一一个是编译器......而不是。所以,你有点卡住了。

有一种一种方式,但是:如果你有一个带有 no 捕获变量的闭包,你可以通过unsafe代码强制复制。也就是说, 点的一个更简单的方法是接受fn(usize) -> f64 而不是,因为它们没有捕获的环境(任何零大小的闭包都可以被重写为函数),并且是Copy

答案 1 :(得分:3)

您可以使用Rc(或Arc!)来获取具有相同不可克隆值的多个句柄。适用于Fn(可通过共享引用调用)闭包。

pub struct MyStruct<F> where F: Fn(usize) -> f64 {
    field: usize,
    mapper: Rc<F>,
    // fields omitted
}

impl<F> Clone for MyStruct<F>
    where F: Fn(usize) -> f64,
{
    fn clone(&self) -> Self {
        MyStruct {
            field: self.field,
            mapper: self.mapper.clone(),
           ...
        }
    }
}

请记住,#[derive(Clone)]对于克隆来说是一个非常有用的方法,但它的配方并不总能为这种情况做正确的事情;这是一个这样的案例。

答案 2 :(得分:3)

从Rust 1.26.0开始,如果所有捕获的变量都执行,则闭包实现CopyClone

#[derive(Clone)]
pub struct MyStruct<F>
where
    F: Fn(usize) -> f64,
{
    field: usize,
    mapper: F,
}

fn main() {
    let f = MyStruct {
        field: 34,
        mapper: |x| x as f64,
    };
    let g = f.clone();
    println!("{}", (g.mapper)(3));
}

答案 3 :(得分:0)

您可以使用trait objects为您的结构实现$body='<p>The man was <a href="http://www.example.com/video/">dancing like a little boy</a> while all kids were watching ... </p>'; echo preg_replace('/< a.*?>|<a.*?>|<\/a>/', ' ', $body);

Сlone