Возьмите "Итератор" вместо "Vec", когда это возможно?

Когда функция принимает ряд значений в качестве параметра, считается ли он хорошим стилем для принятия Iterator<T> вместо Vec<T>?

Таким образом, вызывающий может самостоятельно решить, как хранится серия (внутри Vec, a [T; N] или что-либо еще, на самом деле Option<T> должно быть возможно!). Кроме того, это устраняет необходимость конвертировать все, что у вас есть, в Vec, а также после применения некоторых модификаторов Iterator не требуется .collect()! Поэтому он также должен быть быстрее!

Я что-то упустил или так оно и должно быть сделано?

Ответ 1

Такая функция, которую вы описываете, обычно должна обычно иметь IntoIterator<Item = T>; поэтому он может принимать как Iterator<T>, так и Vec<T> в качестве входных данных.

Это также можно сочетать с другими методами; например, этот метод concat будет принимать &[&str] (и, следовательно, &Vec<&str> с помощью auto deref/ref coercion), &[String] (и, следовательно, &Vec<String>), итератор &str, a String, и так далее:

use std::borrow::Borrow;

fn concat<T: Borrow<str>, Iter: IntoIterator<Item = T>>(iter: Iter) -> String {
    iter.into_iter()  // -> impl Iterator<Item = T>
        .map(|s| s.borrow()) // -> impl Iterator<Item = &str>
        .collect()  // -> String
}

(Этот конкретный пример на самом деле обычно лучше подходит для SliceConcatExt, поскольку он способен рассчитать, как долго конечный результат будет впереди, и таким образом распределить правая длина строки, но это просто доказательство концепции и то, как можно комбинировать несколько причудливых методов.)