Я не могу точно сказать, что именно вы ищете, но - судя по сигнатуре do_some
- я полагаю, что у вас есть Vec<String>
, функция, работающая на String
, возвращающая Result<String, bool>
, иВы хотите применить эту функцию к каждому элементу в Vec
и получить их в Vec
, если все Ok
.Если вы встретите Err
, вы хотите вернуть Err
.Это может быть достигнуто следующим образом:
fn do_some(tokens: Vec<String>) -> Result<Vec<String>, bool> {
tokens
.into_iter()
.map(|token: String| Ok(token)) // or any other Fn(String)->Result<String, bool>
.map(|token: Result<String, bool>| token.map(|s| s + "a"))
.collect()
}
Это использует collect
, полагаясь на FromIter
, и вы можете преобразовать итератор по Result
s вResult
.
Обратите внимание, что вы можете сделать все это более общим:
- Вход не обязательно должен быть
Vec
, это может бытьIterator
более String
с. - Мы можем параметризовать его с помощью функции преобразования, которая преобразует один
String
в Result<String, bool>
, или - чтобы быть более общим - в Result<String, ErrorType>
для некоторыхErrorType
. - Вам не обязательно нужен
Vec
в качестве успешного типа возврата, но все, что реализует FromIter
(который часто является контейнерным типом).
Первый шаг для этого может выглядеть следующим образом:
fn do_some<
ErrorType,
Tokens: std::iter::IntoIterator<Item=String>, // an iterable yielding String
StringToResult: Fn(String) -> Result<String, ErrorType>,
>(
tokens: Tokens,
string_to_result: StringToResult,
) -> Result<Vec<String>, ErrorType> {
tokens
.into_iter()
.map(|s| string_to_result(s).map(|s| s + "a"))
.collect()
}
, который можно использовать следующим образом:
fn main() {
println!("{:?}",
do_some(vec!["i1".to_string(), "i2".to_string(), "i3".to_string()], |s| {
if s.starts_with("i") {
Ok(s)
} else {
Err(s + " i does not start with i")
}
})
);
println!("{:?}",
do_some(vec!["i1".to_string(), "i2".to_string(), "A3".to_string()], |s| {
if s.starts_with("i") {
Ok(s)
} else {
Err(s + " i does not start with i")
}
})
);
}