1
\$\begingroup\$

In my program, I want to either read from a file or stdin depending on the arguments. I did this function to collect input:

use { io::{Read, stdin, Error as IoError} };

fn collect_inputs(args: &Args) -> Result<Vec<Box<dyn Read>>, IoError> {
    Ok(match args.files { // args.files is a Option<Vec<String>>
        Some(paths) => paths
            .into_iter()
            .map(File::open)
            .collect::<Result<Vec<_>, _>>()?
            .into_iter()
            .map(|file| Box::new(file) as Box<dyn Read>)
            .collect::<Vec<_>>(),
        None => vec![Box::new(stdin()) as Box<dyn Read>],
    })
}

The thing is that to use the ? operator to propagate the error to the caller, the only way I found is to convert the Map to a Result using collect, then convert it back to an iterator to wrap it in a Box since I want to return a dynamic type that implements Read, no matter if the type is Stdin or File.

But I find it kind of ugly and think there are unnecessary steps going on. Isn't there a way to improve this code by removing the calls between the two map calls?

\$\endgroup\$
2
  • 3
    \$\begingroup\$ Welcome to Code Review! The current question title, which states your concerns about the code, is too general to be useful here. Please edit to the site standard, which is for the title to simply state the task accomplished by the code. Please see How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ Commented Apr 20 at 14:23
  • \$\begingroup\$ Are you aware of clap_stdin? \$\endgroup\$ Commented Apr 22 at 7:52

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.