我应该使用切片还是迭代器作为函数参数?

Vas*_*kov 1 collections rust

Rust 的最佳实践是什么?如果现在事实上可以工作,我是否应该需要切片 迭代器作为函数参数?

切片插图:

fn my_function(elements: &[i32]) {
  for element in elements {
    do_something(element);
  }
}
fn main() {
  let my_vec = vec![1, 2, 3, ...];
  my_function(&my_vec);
}
Run Code Online (Sandbox Code Playgroud)

迭代器说明:

fn my_function(elements: impl IntoIterator<Item = impl Borrow<i32>>) {
    for e in elements {
        do_something(*e.borrow());
    }
}
fn main() {
    let v = vec![1, 2, 3];
    my_function(&v);
}
Run Code Online (Sandbox Code Playgroud)

具体来说,我想在需要时优化易于维护和修改的代码。

在其他语言中,有些人建议在设计时选择功能最弱且最精确的类型。
在其他一些领域,尤其是在 Java 中经常遇到的情况,通常需要最抽象的类型。

鲁斯特的故事是什么?有什么特别注意事项吗?
我的一般直觉是需要切片,保持简单,并在需要时进行更改。如果我理解正确的话,它也可能对性能有好处。还有其他考虑吗?

Cha*_*man 5

官方Rust API 指南对此进行了明确处理:

函数通过使用泛型 (C-GENERIC) 最小化有关参数的假设

函数对其输入做出的假设越少,它的用途就越广泛。

更喜欢

fn foo<I: IntoIterator<Item = i64>>(iter: I) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

超过任何一个

fn foo(c: &[i64]) { /* ... */ }
fn foo(c: &Vec<i64>) { /* ... */ }
fn foo(c: &SomeOtherCollection<i64>) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

如果函数只需要迭代数据。

更一般地说,考虑使用泛型来确定函数需要对其参数做出的假设。

没有任何性能考虑,因为通用函数将单态化并且通用等效代码与使用切片相同。不过,代码的编译速度可能会较慢。

然而,这仅涉及公共职能。在私人职能中,这是主观的。我更喜欢在大多数情况下采用切片并仅在需要时更改它,以避免编译时成本并使代码更短、更清晰。