2015-09-28 57 views
3

我需要得到宏觀重複元素的索引寫下面的代碼: 如何獲得宏重複單一元素的索引

struct A { 
    data: [i32; 3] 
} 

macro_rules! tst { 
    ($($n:ident),*) => { 
     impl A { 
      $(
       fn $n(self) -> i32 { 
        self.data[?] // here I need the index 
       } 
      ),* 
     } 
    } 
} 

我知道做這件事:只是告訴用戶編寫用手指數:

($($i:ident => $n:ident),*) 

但是有沒有不需要用戶的動作更優雅的方式?

+0

你在做什麼聽起來很可能是一個壞主意。你應該在可行的情況下支持其他設計例如製作一個'struct A {one:i32,two:i32,three:i32}'。 –

+0

@ChrisMorgan。事實上,它涉及實現像四元數的矢量,其中每種類型的長度都不相同,並且需要不同的訪問器。我認爲如果我爲他們全部使用一個代碼,它可以簡化工作。你爲什麼認爲這是一個壞主意? – Lodin

+0

我無法掌握你實際上正在努力達成的目標。你能分享一個完整的代碼示例嗎? –

回答

4

最簡單的方法是使用遞歸,就像這樣:

struct A { 
    data: [i32; 3] 
} 

macro_rules! tst { 
    (@step $_idx:expr,) => {}; 

    (@step $idx:expr, $head:ident, $($tail:ident,)*) => { 
     impl A { 
      fn $head(&self) -> i32 { 
       self.data[$idx] 
      } 
     } 

     tst!(@step $idx + 1usize, $($tail,)*); 
    }; 

    ($($n:ident),*) => { 
     tst!(@step 0usize, $($n,)*); 
    } 
} 

tst!(one, two, three); 

fn main() { 
    let a = A { data: [10, 20, 30] }; 
    println!("{:?}", (a.one(), a.two(), a.three())); 
} 

注意,我改變了方法採取&self,而不是self,因爲它使書寫在main功能更容易的例子。 :)

遞歸中的每一步只是將1添加到索引。由於大量的整數推斷,使用「類型化」整數文字來避免編譯速度減慢是一個好主意。

+0

哇。真棒。它只是讓我失去了理智。 Rust仍然繼續給我驚喜:)非常感謝你,這是非常有趣的解決方案! – Lodin

相關問題