2016-12-05 41 views
5

Rust'u öğrenmeye çalışıyorum ve daha önce yaptığım birçok kişi gibi pratik yapmak için bir Fibonacci dizisi yineleyici yazdım. İlk geçişim u32 s kullanıldı ve iyi çalıştı, bu yüzden genel bir sürüm yazmaya karar verdim. Bu benim sonucudur: Rust'ta aşırı klonlama nasıl önlenir?

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(), 
     } 
    } 
} 

Ben u32 ve num::BigUint ile bu test, ve iyi çalışıyor. Yine de, next yöntemindeki tüm klonlama konusunda endişeliyim. Özellikle, ekleme adımı sırasında neden klonlamaya ihtiyacım olduğunu anlamıyorum.

Bunu, Rust'un daha gelişmiş referans kavramlarından bazılarını kullanarak yazmak için daha iyi bir yol olduğundan şüphe duyuyorum, ama şimdiye kadar bunu çözemedim.

cevap

7

çözüm şöyle bir where maddesini kullanmaktır:

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) 
    } 
} 

Özellikle, for<'a> &'a T: Add<&'a T, Output=T> maddesi "herhangi ömür boyu 'a, &'a T&'a T ve Output=T bir RHS ile Add uygulamalıdır gelince okur Yani,. Yeni bir T almak için iki &T s ekleyebilirsiniz.

Bununla birlikte, geriye kalan tek sorun,kullanılarak yapılabilir. 210.

Ayrıca başka yerdeki kısıtlamaları sadeleştirme özgürlüğünü de aldım (yalnızca numaralı Integer'a ihtiyacınız var).

+0

Hızlı bir takip: Yapının kendisinde herhangi bir özellik sınırı koymadığınızı fark ettim, sadece uygulamalarda. Bu bir Rust sözleşmesi mi? –

+0

@MarkTozzi Çoğunlukla kişisel tercihlere göre. Bir türü "yanlış kullanmak" için daha zor yapmak istiyorsanız, her yerde sınırları tekrarlayabilirsiniz, ancak bir örnek için overkill görünüyordu. –

+0

Herkesin de merak ettiği durumda: "Nerede" yapıtı (Magic of the Magic) Yüksek Sırada Trait Bounds (HRTBs) olarak adlandırılır ve burada https://doc.rust-lang.org/nomicon/hrtb adresinde belgelenir. html – Sebastian