如何避免Rust中过多的克隆?

Mar*_*zzi 7 rust

我正在尝试学习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(),
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我用a u32和a 测试了num::BigUint它,它工作正常.我关心的是该next方法中的所有克隆.特别是,我不明白为什么我需要在添加步骤中克隆.

我怀疑有一种更好的方法可以使用Rust的一些更高级的参考概念来编写它,但到目前为止我还没有想到它.

DK.*_*DK. 9

解决方案是使用如下的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)
    }
}
Run Code Online (Sandbox Code Playgroud)

具体来说,for<'a> &'a T: Add<&'a T, Output=T>条款内容为"对任何生命周期'a,&'a T必须实现Add用的RHS &'a TOutput=T,也就是说,你可以添加两个&Ts到获得新的T.

有了这个,唯一剩下的问题是改变周围的值,这可以使用swap.

我也冒昧地简化其他地方的限制(你只需要One,而不是Integer).

  • 如果有人也想知道:“where for”构造被称为高阶特征边界(HRTB)的魔力,并记录在此处https://doc.rust-lang.org/nomicon/hrtb.html (2认同)