如何通过在Rust中调用变量的方法来避免重复重新声明变量?

如何通过在Rust中调用变量的方法来避免重复重新声明变量?,rust,variable-assignment,Rust,Variable Assignment,我在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();

我在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
}

into()
方法没有什么特别之处,它只是一个示例,在这个示例中,您可以在函数开始时以一种易于消除重复的方式重新声明许多参数。

当然,您可以使用递归宏执行此操作:

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);
    }
}

当然,可以使用递归宏执行此操作:

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);
    }
}

正如@paholg所指出的,使用宏可以很容易地做到这一点。但是,您不需要使用递归,这将稍微慢一点,也不太有用(在编译器放弃之前,您只能递归有限的次数)

我还冒昧地使用了
Into::Into
方法的完全限定名,以避免名称冲突问题:

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

正如@paholg所指出的,使用宏可以很容易地做到这一点。但是,您不需要使用递归,这将稍微慢一点,也不太有用(在编译器放弃之前,您只能递归有限的次数)

我还冒昧地使用了
Into::Into
方法的完全限定名,以避免名称冲突问题:

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

这是更好的答案。我最近一直在研究一些非常复杂的宏,所以我想我脑子里有递归。这是更好的答案。我最近一直在研究一些非常复杂的宏,所以我想我脑子里有递归。