用 C++ template 實作九九乘法表
我們可以用 Rust 的generic type 做到類似的事情,概念是一樣的
試過用Rust 的Macro 來寫,這樣會遇到問題,如下如果我們接到一個table,對它展開:
macro_rules! node { ( $x:expr, $y:expr ) =>; { println!("{}*{}={}", $x, $y, $x*$y); } }
這樣一個node 是沒問題的,但在進行row 展開時,macro 並不像template 一樣會對特化優先匹配,因此
macro_rules! row { ( $x:expr, 1) =>; { node!($x, $y) }; ( $x:expr, $y:expr ) =>; { row!($x, $y-1) node!($x, $y) }; }是沒有用的,編譯時仍會在展開 row! 那行發出警告recursion limit reached。
用generic 的function 來寫,其實就一般般,我們定義Node, Row, Table function,使用型別T 作為generic型別,Table 在row 不為一的時候會特化為row 少一的 Table 和Row;Row 在col 不為一的時候會特化為col 少一的Row 和Node,反之則只特化為Row 跟Node。
為了特化時的運算,我們對型別 T至少要有下面那一大排的要求:
- Copy: 可複製,否則類似下面的row 被傳入Row 跟Node function 中,use moved value
- PartialOrd: 可比較大小,用在 col > T::one()
- One: T 有定義 one(),對大多數的Rust primitive type,都有定義Zero 跟One 兩種屬性,可以用在Add 跟 Mul,即Add T::zero() 其值不變,Mul T::one() 其值不變,不知道為啥Rust 核心對這部分好像會大改,用了它們也要在程式加上#![feature(zero_one)]才會動
- Sub<T, Output=T>: T可以減T 得到一個T,為了下面的 col-T::one(),
- Mul<T, Output=T>: T可以乘T 得到一個T,為了最裡面的 row * col = (row * col)
fn RowTable function 類似,只是判斷對象變成row;Node function 則是印出結果。主程式就呼叫 Table(9u32, 9u32) 就能看見漂亮的九九乘法表了。(row: T, col: T) { where T: Copy+PartialOrd+One+Sub +Mul +Debug { if col > T::one() { Row(row, col-T::one()); } Node(row, col); print!("\t"); }
怎麼說呢,感覺跟C++ template 的寫法還是有點不同的感覺呢…
沒有留言:
張貼留言