5
\$\begingroup\$

I'm just starting out in Rust and I find the concept of ownership confusing so I wrote an implementation of the echo command. I would like to know if I could have set the initial value on the echo variable any better or just any general improvements.

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut echo: String;
    if let Some(string) = args.get(1) {
        echo = string.to_string();
    } else {
        return;
    }

    for arg in &args[2..] {
        echo.push(' ');
        echo.push_str(arg.as_str());
    }
    echo.push('\n');

    println!("{}", echo);
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Actually this answer cover almost all I could say. \$\endgroup\$ – Stargateur Sep 12 '18 at 17:46
  • \$\begingroup\$ @Stargateur Thanks a lot! I forgot to mention I didn't want to use any external crates so that works really well for me. \$\endgroup\$ – Genuinebyte Sep 12 '18 at 17:55
3
\$\begingroup\$

I would not say I am any more proficient but I would make these changes if I wrote it.

  • skip(1) first arg.
  • join(" ") instead of iterate though args.

You do not need a mutable value.

use std::env;

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();

    if args.len() == 0 {
        println!("");
    } else {
        println!("{}", args.join(" "));
    }
}

I would do one more thing and send to stdout sinse your mimicking echo, but maybe to much for this answer.

\$\endgroup\$
  • \$\begingroup\$ I didn't realize env::Args implemented the Iterator trait. It's definitely more elegant than my code, thanks! \$\endgroup\$ – Genuinebyte Sep 13 '18 at 3:22
  • \$\begingroup\$ Thank you. Honestly there are more cool tricks, I think you can get away with just join no 'if'. \$\endgroup\$ – Brandon Clark Sep 13 '18 at 7:45
  • \$\begingroup\$ @Genuinebyte I didn't realize env::Args implemented the Iterator trait. — where did you think collect was coming from? \$\endgroup\$ – Shepmaster Sep 14 '18 at 0:27
3
\$\begingroup\$
  1. Use Iterator::skip instead of collecting the arguments into a Vec and then skipping over it.

  2. This implementation should not have any allocation, whatsoever. Neither collecting the arguments or building an output string is needed.

use std::env;

fn main() {
    let mut args = env::args().skip(1);

    if let Some(arg) = args.next() {
        print!("{}", arg);

        for arg in args {
            print!(" {}", arg);
        }
    }

    println!();
}
\$\endgroup\$
  • \$\begingroup\$ Great thing about rust is the low-level language with so many options. \$\endgroup\$ – Brandon Clark Sep 14 '18 at 5:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.