2016-11-12 36 views
1

我正在使用Into在Rust中的多個參數,並希望避免許多任務和愚蠢的錯誤。如何通過在Rust中調用其方法來避免重複聲明變量?

pub fn my_fancy_function<T>(v: T, u: T, i: T, l: T, j: T) 
    where T: Into<MyStruct> 
{ 
    let v = v.into(); 
    let u = u.into(); 
    let i = l.into(); // Oops, I transposed these! 
    let l = i.into(); 
    let j = j.into(); 
    // some code 
} 

有沒有辦法避免寫出大塊的任務?宏可能能夠做到這一點:

expand_into!(v, u, i, l, j); 

沒有什麼特別之處into()方法,這只是一個例子,在函數的方式,可能是開始,你可能經常重新申報很多爭論容易重複刪除。

回答

5

由於@paholg指出,你可以用宏做到這一點很容易。但是,你不需要使用遞歸,這會稍微慢一點,也不會太有用(在編譯器放棄之前,你只能遞減有限的次數)。

我還拿了使用Into::into方法的完全限定名稱,以避免名稱衝突問題的自由:

macro_rules! expand_into { 
    ($($names:ident),*) => { 
     $(let $names = ::std::convert::Into::into($names);)* 
    }; 
} 
+0

這是更好的答案。最近我一直在研究一些非常複雜的宏,所以我想我的思維有遞歸。 – paholg

2

當然,你可以用遞歸宏做到這一點:

macro_rules! expand_into { 
    () =>(); 
    ($head:ident $(, $tail:ident)*) => (
     let $head = $head.into(); 
     expand_into!($($tail),*); 
    ); 
} 

,並測試它:

fn main() { 
    let a = 1; 
    let b = 2; 
    let c = 3; 
    let d = 4; 

    expand_into!(a, b, c, d); 

    // Need to do something that reveals types so the compiler knows 
    // which `into()` functions to call. 
    if let (Some(x), Some(y), Some(z), Some(w)) = (a, b, c, d) { 
     println!("{}, {}, {}, {}", x, y, z, w); 
    } 
}