Rust程式語言中並沒有內建一種能夠代表所基本數值型別(u8, i16, f64等)的型別,也因此當我們在定義函數或方法的時候,如果要透過參數傳入數值型別的值的話,通常會需要以「fn xxx_u8」、「fn xxx_i16」、「fn xxx_f64」的方式將每個不同的數值型別都獨立定義出來。您可能會想問:為什麼不用泛型?那是因為就算用泛型,我們還是沒有辦法限制泛型的型別參數只能是數值型別。



所以,為了解決這個問題,我們就必須要替Rust程式語言中所有的數值型別實作一個共同的特性,如此一來在定義函數或方法,甚至是其它資料結構時,都可以利用這個特性來表示所有型別的數值。

Number As

「Number As」是筆者開發的套件,可以替Rust程式語言中所有的數值型別實作NumberAsNumber特性,使得它們可以自動互相轉換。

Crates.io

Cargo.toml

number-as = "*"

使用方法

NumberAs

使用use關鍵字來將number_as這個crate底下的NumberAs特性給引用到當前的程式範圍下,如此一來,基本數值都會擁有number_as方法,可以利用Rust編譯器的「型別自動推論」,將數值轉換成其它任意的數值型別。

如以下程式:

use number_as::NumberAs;

let a: i32 = 2u16.number_as();

assert_eq!(2i32, a);

assert_eq!(2i32, 2u16.number_as());

assert_eq!(20i32, 20.6.number_as());

在使用number_as方法時,我們不需要去指定number_as方法回傳的值是什麼型別,Rust編譯器會根據回傳值被使用的地方來自動推論出回傳值的型別。

Number

使用use關鍵字來將number_as這個crate底下的NumberAs特性和Number特性給引用到當前的程式範圍下,如此一來,基本數值都會擁有Number特性。此時若要定義任意數值型別的變數、參數或是欄位,就可以指定它們必須實作Number特性。如以下程式,add方法的參數可以接受任意數值型別的輸入,並且其回傳值的型別也可以由Rust編譯器自動推論出來。

use number_as::{Number, NumberAs};

fn add<T, J, K>(a: T, b: J) -> K where T: Number, J: Number, K: Number, i128: NumberAs<K> {
    let a: i128 = a.number_as();
    let b: i128 = b.number_as();

    let c = a + b;

    c.number_as()
}

assert_eq!(40i32, add(5u8, 35i16));