【问题标题】:How can I create a function with a variable number of arguments?如何创建具有可变数量参数的函数?
【发布时间】:2015-03-09 20:51:02
【问题描述】:

如何在 Rust 中创建具有可变数量参数的函数?

喜欢这个Java代码:

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

【问题讨论】:

    标签: rust variadic-functions


    【解决方案1】:

    一般来说,你不能 - Rust 不支持可变参数函数,除非与使用可变参数的 C 代码互操作。

    this 的情况下,由于所有参数都是同一类型,因此您可以接受切片:

    fn foo(args: &[&str]) {
        for arg in args {
            println!("{}", arg);
        }
    }
    
    fn main() {
        foo(&["hello", "world", "I", "am", "arguments"]);
    }
    

    (Playground)

    除此之外,您还可以显式接受可选参数:

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

    (Playground)

    如果您需要接受许多参数,无论是否可选,您可以实现一个构建器:

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

    (Playground)

    【讨论】:

      【解决方案2】:

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

      macro_rules! print_all {
          ($($args:expr),*) => {{
              $(
                  println!("{}", $args);
              )*
          }}
      }
      
      fn main() {
          print_all!(1, 2, "Hello");
      }
      

      Playground

      作为另一个例子,如果你想折叠参数,你可以这样做:

      macro_rules! sum {
          ($($args:expr),*) => {{
              let result = 0;
              $(
                  let result = result + $args;
              )*
              result
          }}
      }
      
      fn main() {
          assert_eq!(sum!(1, 2, 3), 6);
      }
      

      Playground

      另一个例子见Rust book's simplified implementation of vec![...]

      【讨论】:

        【解决方案3】:
        fn variable_func<T>(_vargs: &[T]) {}
        
        fn main() {
            variable_func(&[1]);
            variable_func(&[1, 2]);
            variable_func(&["A", "B", "C"]);
        }
        

        【讨论】:

        • @Shepmaster 现在编译。是的,我同意分配部分。有没有类似的方法不用分配?
        • 啊,是的,这里真的不需要宏。我会根据你的评论修改答案。
        • 如果我想让函数取得数组的所有权怎么办?
        • @qiuxiafei 除非您可以硬编码数组的大小(从而使其不是可变参数),或者您为每个要支持的 [T; N] 编写一个变体,您必须提供它是Vec&lt;T&gt;
        • @kbolino 是的,我认为 Vec 是唯一的解决方案。
        猜你喜欢
        • 2012-11-23
        • 1970-01-01
        • 2018-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-19
        • 1970-01-01
        相关资源
        最近更新 更多