Próbuję nauczyć się Rusta, i jak wielu przedtem wyruszyłem, aby napisać iterator sekwencji Fibonacciego do ćwiczeń. Mój pierwszy przebieg używał u32
s i działał dobrze, więc postanowiłem spróbować napisać ogólną wersję. To jest mój wynik:Jak uniknąć nadmiernego klonowania w Rust?
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(),
}
}
}
testowałem to z u32
i num::BigUint
, i to działa dobrze. Martwię się jednak o wszystkie klonowania w metodzie . W szczególności nie rozumiem, dlaczego potrzebuję sklonować podczas kroku dodawania.
Podejrzewam, że istnieje lepszy sposób napisania tego przy użyciu bardziej zaawansowanych pojęć odniesienia Rusta, ale jak dotąd nie odkryłem tego.
Jedna szybka odpowiedź: Zauważyłem, że nie wprowadziłeś żadnych ograniczeń w samej strukturze, tylko w implementacjach. Czy to jest konwencja Rusta? –
@MarkTozzi Zwykle zależy to od osobistych preferencji. Możesz wszędzie powtórzyć granice, jeśli chcesz utrudnić "niewłaściwe użycie" typu, ale na przykład wydawało się to przesadzone. –
W przypadku, gdy ktoś się zastanawia: konstrukcja "gdzie dla" jest nazywana (The Magic of) cechami wyższej rangi (HRTB) i jest udokumentowana tutaj https://doc.rust-lang.org/nomicon/hrtb. html – Sebastian