我正在尝试学习Rust,并且在我开始编写Fibonacci序列迭代器进行练习之前就像许多人一样。我的第一遍使用u32
并且工作正常,所以我决定尝试编写通用版本。这是我的结果:
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(),
}
}
}
我使用u32
和num::BigUint
进行了测试,效果很好。我关注next
方法中的所有克隆。特别是,我不明白为什么我需要在添加步骤中克隆。
我怀疑使用Rust的一些更高级的参考概念有更好的方法来写这个,但到目前为止,我还没有想到它。
答案 0 :(得分:8)
解决方案是使用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<'a> &'a T: Add<&'a T, Output=T>
子句的内容为“任何有效期'a
,&'a T
必须实施Add
,其中RHS为&'a T
且Output=T
也就是说,您可以添加两个&T
来获取新的T
。
有了这个,剩下的唯一问题就是改变周围的值,可以使用swap
来完成。
我也冒昧地在其他地方简化约束(你只需要One
,而不是Integer
)。