2015-01-14 47 views
1

我正在嘗試編寫一個類似於內置Range的Rust函數,但我希望返回只有X個數字的東西,並將其作爲列表返回,就是爲什麼我試圖做這個功能: extern crate num;無法創建使用文字零的通用函數

use num::Integer; 

fn positions<T: Integer>(start: T, step: T, len: T) -> Vec<T> { 
    (0..len).map(|i| start + step * i).collect() 
} 

fn main() { 
    println!("{:?}", positions(10, 2, 10)); 
} 

除非我得到一個編譯器錯誤:

error[E0308]: mismatched types 
--> src/main.rs:6:9 
    | 
6 |  (0..len).map(|i| start + step * i).collect() 
    |   ^^^ expected integral variable, found type parameter 
    | 
    = note: expected type `{integer}` 
      found type `T` 
    = help: here are some functions which might fulfill your needs: 
      - .div_floor(...) 
      - .gcd(...) 
      - .lcm(...) 
      - .mod_floor(...) 

error[E0308]: mismatched types 
--> src/main.rs:6:37 
    | 
6 |  (0..len).map(|i| start + step * i).collect() 
    |         ^expected type parameter, found integral variable 
    | 
    = note: expected type `T` 
      found type `{integer}` 

回答

4

問題是0。我現在對確切的規則還不清楚,但讓我們做一般:0是一些特定的整數類型,它可能與T是一樣的,也可能不是。因此,編譯器無法確定range的類型參數應該是什麼。

您可以通過使用Zero::zero解決此問題:

fn positions<T: Integer>(start: T, step: T, len: T) -> Vec<T> { 
    (T::zero()..len).map(|i| start + step * i).collect() 
} 

這使編譯器足夠的餘地來推斷,這兩個參數range是同一類型的。然而,這仍然不夠用Range爲一個迭代器:

error: no method named `map` found for type `std::ops::Range<T>` in the current scope 
--> src/main.rs:8:22 
    | 
8 |  (T::zero()..len).map(|i| start + step * i).collect() 
    |      ^^^ 
    | 
    = note: the method `map` exists but the following trait bounds were not satisfied: `T : std::iter::Step`, `&'a T : std::ops::Add`, `std::ops::Range<T> : std::iter::Iterator` 

不幸的是,防鏽1.17時,Step trait是不穩定的,所以有目前使用穩定的鏽來解決這個問題沒有很好的辦法。

使用不穩定的鏽,你可以要求Step實現:

#![feature(step_trait)] 

extern crate num; 

use num::Integer; 

fn positions<T>(start: T, step: T, len: T) -> Vec<T> 
    where T: Integer + std::iter::Step + Copy, 
      for<'a> &'a T: std::ops::Add<Output = T> 
{ 
    (T::zero()..len).map(|i| start + step * i).collect() 
} 

fn main() { 
    println!("{:?}", positions(10, 2, 10)); 
} 

需要要求T可以複製(或克隆,如果你喜歡),因爲AddMul消耗實現操作數的值,這意味着start + step * i只能被調用一次,除了它需要被多次調用。