Rust 将参数传递给函数n次

Rust 将参数传递给函数n次,rust,rust-macros,Rust,Rust Macros,我正在Rust中试验不同的模式,并希望尝试动态调用具有类似签名但参数数量不同的几个函数之一。例如: fn foo(x: i32) -> i32 { x } fn bar(x1: i32, x2: i32) -> i32 { x1 + x2 } fn baz(x1: i32, x2: i32, x3: i32) -> i32 { x1 + x2 + x3 } 我希望能够将所有参数的值传递给这些方法,以便可以互换调用它们-因此,如果输入是5,我希望能够调用foo(5),bar(5

我正在Rust中试验不同的模式,并希望尝试动态调用具有类似签名但参数数量不同的几个函数之一。例如:

fn foo(x: i32) -> i32 { x }
fn bar(x1: i32, x2: i32) -> i32 { x1 + x2 }
fn baz(x1: i32, x2: i32, x3: i32) -> i32 { x1 + x2 + x3 }
我希望能够将所有参数的值传递给这些方法,以便可以互换调用它们-因此,如果输入是
5
,我希望能够调用
foo(5)
bar(5,5)
,或者
baz(5,5,5,5)
,等等

这似乎最好通过宏或其他语法扩展来实现,但我不确定最好的表达方式。到目前为止,我只是对案例进行了暴力枚举,但这似乎既乏味(为每个案例重新编写相同的表达式)又脆弱(不支持n+1参数):

我遇到过类似的情况,但仍然需要分别列举每个案例

是否有更好的方法可以更灵活地将
fn(X,…)
包装为只接受一个
X
的函数

是一个函数
expand
,可以简单地用函数名调用,并返回“expanded”版本。也就是说,你可以这样使用它:

fn main() {
    let state = 15;
    let vs: Vec<Box<dyn Fn(i32) -> i32>> = vec![
        expand(foo),
        expand(bar),
        expand(baz),
        expand(|x| x+1), // with lambdas
        expand(move |x| x+state), // with stateful lambdas
    ];
    for f in &vs {
        println!("{:?}", f(1));
    }
}

fn foo(x: i32) -> i32 { x }
fn bar(x1: i32, x2: i32) -> i32 { x1 + x2 }
fn baz(x1: i32, x2: i32, x3: i32) -> i32 { x1 + x2 + x3 }

您可以通过调整对
impl\u expand

的调用来扩展参数计数的范围。我不确定是否理解您的问题(或您的意图),但为什么不给函数一个切片或迭代器呢?例如:如果您的输入是
let input=5
,请重复数字:
let slice=iter::repeat(input)。获取(您想要的数字)。collect()
,并将其提供给您的函数。@Boiethios函数签名是固定的-我同意类似迭代器的东西是合理的,但出于我的目的,这里的函数需要位置参数。这个MCVE是一个玩具示例-我的实际用例更复杂,但这是我不确定的部分。如果你想要一种重载多态性,最好是创建一个包含所有参数的结构,并将其作为唯一参数提供给func;然后,为一组元组实现
From
trait,其中包含您想要的所有组合。或者您使用的构建器模式在Rust中非常惯用。但是,如果您不能更改函数签名,那么这将不起作用(甚至,我想知道如何才能帮助您)。也许你的问题应该更明确一些,因为在当前状态下,它似乎太宽泛而无法正确回答。@Boiethios我不知道它有多宽泛-我正在寻找更好的方法来实现
扩展这样所有案例都不必单独枚举。我故意试图缩小问题的范围。A可能是实现这一目标的唯一途径。
fn main() {
    let state = 15;
    let vs: Vec<Box<dyn Fn(i32) -> i32>> = vec![
        expand(foo),
        expand(bar),
        expand(baz),
        expand(|x| x+1), // with lambdas
        expand(move |x| x+state), // with stateful lambdas
    ];
    for f in &vs {
        println!("{:?}", f(1));
    }
}

fn foo(x: i32) -> i32 { x }
fn bar(x1: i32, x2: i32) -> i32 { x1 + x2 }
fn baz(x1: i32, x2: i32, x3: i32) -> i32 { x1 + x2 + x3 }
trait TExpand<T, R, TplDummy> {
    fn call(&self, t: T) -> R;
}
macro_rules! ignore_ident{
    ($id:ident, $($t:tt)*) => {$($t)*};
}
macro_rules! impl_expand{
    () => {};
    ($t0:ident $($t:ident)*) => {
        impl_expand!($($t)*);
        impl<T: Copy, R, F:Fn($(ignore_ident!($t, T),)*)->R> TExpand<T, R, ($(ignore_ident!($t, T),)*)> for F {
            #[allow(unused_variables)] // for nullary function
            fn call(&self, t: T) -> R {
                (self)($(ignore_ident!($t, t),)*)
            }
        }
    }
}
impl_expand!(t0 t1 t2 t3);

fn expand<TplDummy, T, R, F:TExpand<T, R, TplDummy>+'static>(f: F) -> Box<dyn Fn(T)->R> {
    Box::new(move |t| f.call(t))
}