Я изучаю Rust, и я натолкнулся на следующий шаблон, который сворачивает итератор Result<Vec<_>, _>
s в один большой Vec<_>
, терпя неудачу, если какой-либо из результатов итератора потерпел неудачу:
fn accumulate<T, E>(it: impl Iterator<Item = Result<Vec<T>, E>>) -> Result<Vec<T>, E> {
let mut result = Vec::new();
for mut ts in it {
result.append(&mut ts?)
}
Ok(result)
}
Я предполагаю, что можно написать очень короткую версию этой функции в «функциональном стиле», и я изо всех сил пытаюсь ее найти. Морально я хотел бы сделать что-то вроде
it.map(|v| v?.into_iter()).flatten().collect()
, но это не проверка типа. Запустив небольшие примеры, я думаю, что смысл flatten
в том, чтобы молча отбрасывать результаты ошибок, но вместо этого я бы хотел как-то «сопоставить flatten
с Result
s». Я также знаю, что в общем случае вы не можете собрать, скажем, итератор типа
impl Iterator<Item = Result<impl Iterator<Item = T>, Error>>
в итератор
Result<impl Iterator<Item = impl Iterator<Item = T>>, Error>
, так как вам действительно нужно выполнить все вычисления во внешнем итераторе, чтобы узнать конечный результат. Тем не менее, кажется, что вы можете сделать эту работу в этом особом случае, когда вы хотите .flatten()
, а затем .collect()
сразу после.
Наконец, я вижу, что это collect()
дает мне путь построить вектор векторов из it
, и тогда я смогу сгладить этот вектор в один большой вектор, который я хочу. Но у этого есть много ненужных выделений памяти.
Может ли стандартная библиотека помочь вам сделать это эффективным, Rust-i c способом?