【问题标题】:How to avoid excessive cloning in Rust?如何避免 Rust 中的过度克隆?
【发布时间】:2016-12-05 00:01:02
【问题描述】:

我正在尝试学习 Rust,并且像我之前的许多人一样着手编写一个 Fibonacci 序列迭代器进行练习。我的第一遍使用u32s 并且工作正常,所以我决定尝试编写一个通用版本。这是我的结果:

use num::Integer;
use std::ops::Add;

pub struct Fibonacci<T: Integer + Add + Clone> {
    nth: T,
    n_plus_one_th: T,
}

impl<T: Integer + Add + Clone> Iterator for Fibonacci<T> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let temp = self.nth.clone();
        self.nth = self.n_plus_one_th.clone();
        self.n_plus_one_th = temp.clone() + self.n_plus_one_th.clone();
        Some(temp)
    }
}

impl<T: Integer + Add + Clone> Fibonacci<T> {
    pub fn new() -> Fibonacci<T> {
        Fibonacci {
            nth: T::one(),
            n_plus_one_th: T::one(),
        }
    }
}

我用u32num::BigUint 对此进行了测试,它运行良好。不过,我担心next 方法中的所有克隆。特别是,我不明白为什么我需要在添加步骤中进行克隆。

我怀疑有更好的方法来使用 Rust 的一些更高级的参考概念来编写这个,但到目前为止我还没有想出来。

【问题讨论】:

    标签: rust


    【解决方案1】:

    解决方案是像这样使用where 子句:

    extern crate num;
    
    use num::One;
    use std::ops::Add;
    
    pub struct Fibonacci<T> {
        nth: T,
        n_plus_one_th: T,
    }
    
    impl<T> Fibonacci<T>
        where T: One
    {
        pub fn new() -> Fibonacci<T> {
            Fibonacci {
                nth: T::one(),
                n_plus_one_th: T::one(),
            }
        }
    }
    
    impl<T> Iterator for Fibonacci<T>
        where for<'a> &'a T: Add<&'a T, Output = T>
    {
        type Item = T;
        fn next(&mut self) -> Option<T> {
            use std::mem::swap;
            let mut temp = &self.nth + &self.n_plus_one_th;
            swap(&mut self.nth, &mut temp);
            swap(&mut self.n_plus_one_th, &mut self.nth);
            Some(temp)
        }
    }
    

    具体而言,for&lt;'a&gt; &amp;'a T: Add&lt;&amp;'a T, Output=T&gt; 子句读取为“对于任何生命周期 'a&amp;'a T 必须实现 Add,RHS 为 &amp;'a TOutput=T。也就是说,您可以添加两个 &amp;T s 获得一个新的T

    这样,剩下的唯一问题就是改变值,这可以使用swap 来完成。

    我还冒昧地简化了其他地方的约束(您只需要One,而不是Integer)。

    【讨论】:

    • 一个快速跟进:我注意到您没有在结构本身上设置任何特征边界,仅在实现上。这是一个 Rust 约定吗?
    • @MarkTozzi 这主要取决于个人喜好。如果你想让“误用”一个类型变得更加困难,你可以在任何地方重复边界,但对于一个例子来说,这似乎有点过分了。
    • 如果有人也想知道:“where for”构造被称为(The Magic of)Higher-Rank Trait Bounds (HRTB),并在此处记录 doc.rust-lang.org/nomicon/hrtb.html
    猜你喜欢
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 2011-10-03
    • 2012-10-03
    • 1970-01-01
    • 2019-12-15
    • 2019-02-25
    相关资源
    最近更新 更多