如何创建一个具有可变参数的函数?

94

我该如何在Rust中创建一个可以接受可变数量参数的函数?

就像这个Java代码:

void foo(String... args) {
    for (String arg : args) {
        System.out.println(arg);
    }
}
3个回答

104
通常情况下,你不能这样做 - Rust不支持变参函数,除非与使用varargs的C代码进行交互。
在这种情况下,由于你所有的参数都是相同类型,你可以接受一个slice。
fn foo(args: &[&str]) {
    for arg in args {
        println!("{}", arg);
    }
}

fn main() {
    foo(&["hello", "world", "I", "am", "arguments"]);
}

(游乐场)

除此之外,您可以明确接受可选参数:

fn foo(name: &str, age: Option<u8>) {
    match age {
        Some(age) => println!("{} is {}.", name, age),
        None      => println!("Who knows how old {} is?", name),
    }
}

fn main() {
    foo("Sally", Some(27));
    foo("Bill", None);
}

(游乐场)

如果您需要接受许多参数,可选或不可选,您可以实现一个构建器:

struct Arguments<'a> {
    name: &'a str,
    age: Option<u8>,
}

impl<'a> Arguments<'a> {
    fn new(name: &'a str) -> Arguments<'a> {
        Arguments {
            name: name,
            age: None
        }
    }

    fn age(self, age: u8) -> Self {
        Arguments {
            age: Some(age),
            ..self
        }
    }
}

fn foo(arg: Arguments) {
    match arg.age {
        Some(age) => println!("{} is {}.", arg.name, age),
        None      => println!("Who knows how old {} is?", arg.name),
    }
}

fn main() {
    foo(Arguments::new("Sally").age(27));
    foo(Arguments::new("Bill"));
}

(游乐场)


34
在一般情况下,如果你的类型可能不同,你可以使用宏:

在一般情况下,您的类型可能会有所不同,您可以使用宏:

macro_rules! print_all {
    ($($args:expr),*) => {{
        $(
            println!("{}", $args);
        )*
    }}
}

fn main() {
    print_all!(1, 2, "Hello");
}

游乐场

另一个例子,如果你想遍历参数,你可以这样做:

macro_rules! sum {
    ($($args:expr),*) => {{
        let result = 0;
        $(
            let result = result + $args;
        )*
        result
    }}
}

fn main() {
    assert_eq!(sum!(1, 2, 3), 6);
}

游乐场

参见Rust 书中对 vec![...] 的简化实现的另一个例子。


8
fn variable_func<T>(_vargs: &[T]) {}

fn main() {
    variable_func(&[1]);
    variable_func(&[1, 2]);
    variable_func(&["A", "B", "C"]);
}

@Shepmaster 现在可以编译了。是的,我同意分配部分。有没有一种类似的方法可以不用分配? - creativcoder
啊,是的,在这里真的不需要宏。我会根据您的评论修改答案。 - creativcoder
如果我想让函数拥有该数组,该怎么办? - qiuxiafei
3
除非你能够硬编码数组的大小(从而使其不具有可变长度性质),或者为你想要支持的每个 [T; N] 写一个变种,否则你将不得不给它一个 Vec<T> - kbolino
@kbolino 是的,我认为 Vec<T> 是唯一的解决方案。 - qiuxiafei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接