2016-11-12 2 views
1

私はRustの複数の引数にIntoを使用しており、多くの割り当てや愚かな間違いを避けたいと考えています。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()方法について何も特別なことは、それができる方法で、関数の開始時にちょうどたとえば、あなたが頻繁に再宣言するかもしれない多くの引数だ、ありません簡単に重複排除されます。

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

をし、それをテストするために:

答えて

5

@paholgが指摘したように、あなたはマクロで簡単にこれを行うことができます。しかし、は再帰を使用する必要はありません。これは少し遅く、少し役に立たなくなります(コンパイラーがあきらめる前に限られた回数しか再帰できません)。

私も、名前の衝突の問題を回避するために、Into::into方法の完全修飾名を使用しての自由を取った:

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

これは良い答えです。私は最近、かなり複雑なマクロに取り組んできたので、私は心に再帰を持っていると思う。 – paholg

2

確かに、あなたは再帰的なマクロでこれを行うことができます

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); 
    } 
} 
関連する問題