Checking against user input and returns a response based on that input












1












$begingroup$


How could I use enums in the following block of code to simplify it? The block is a program that has a command interpreter that returns different data based on user input. Is there a way I could easily apply enums and a match statement to the logic here?



use std::io;

fn main() {
let version = String::from("0.0.1");
let mut input = String::new();

shell(&mut input, &version);
}

fn shell(input: &mut String, version: &String) {
input.clear();
match io::stdin().read_line(input) {
Ok(b) => {
if &input.trim() == &"ver" || &input.trim() == &"what are you" {
println!("C ute R ust A mateur B eginner Shell ver: {}", version);
shell(input, version);
} else {
println!("Command '{}' Not Recognized", input);
shell(input, &version);
}
}
Err(err) => panic!("incorrect"),
}
}









share|improve this question









New contributor




rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$

















    1












    $begingroup$


    How could I use enums in the following block of code to simplify it? The block is a program that has a command interpreter that returns different data based on user input. Is there a way I could easily apply enums and a match statement to the logic here?



    use std::io;

    fn main() {
    let version = String::from("0.0.1");
    let mut input = String::new();

    shell(&mut input, &version);
    }

    fn shell(input: &mut String, version: &String) {
    input.clear();
    match io::stdin().read_line(input) {
    Ok(b) => {
    if &input.trim() == &"ver" || &input.trim() == &"what are you" {
    println!("C ute R ust A mateur B eginner Shell ver: {}", version);
    shell(input, version);
    } else {
    println!("Command '{}' Not Recognized", input);
    shell(input, &version);
    }
    }
    Err(err) => panic!("incorrect"),
    }
    }









    share|improve this question









    New contributor




    rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      1












      1








      1





      $begingroup$


      How could I use enums in the following block of code to simplify it? The block is a program that has a command interpreter that returns different data based on user input. Is there a way I could easily apply enums and a match statement to the logic here?



      use std::io;

      fn main() {
      let version = String::from("0.0.1");
      let mut input = String::new();

      shell(&mut input, &version);
      }

      fn shell(input: &mut String, version: &String) {
      input.clear();
      match io::stdin().read_line(input) {
      Ok(b) => {
      if &input.trim() == &"ver" || &input.trim() == &"what are you" {
      println!("C ute R ust A mateur B eginner Shell ver: {}", version);
      shell(input, version);
      } else {
      println!("Command '{}' Not Recognized", input);
      shell(input, &version);
      }
      }
      Err(err) => panic!("incorrect"),
      }
      }









      share|improve this question









      New contributor




      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      How could I use enums in the following block of code to simplify it? The block is a program that has a command interpreter that returns different data based on user input. Is there a way I could easily apply enums and a match statement to the logic here?



      use std::io;

      fn main() {
      let version = String::from("0.0.1");
      let mut input = String::new();

      shell(&mut input, &version);
      }

      fn shell(input: &mut String, version: &String) {
      input.clear();
      match io::stdin().read_line(input) {
      Ok(b) => {
      if &input.trim() == &"ver" || &input.trim() == &"what are you" {
      println!("C ute R ust A mateur B eginner Shell ver: {}", version);
      shell(input, version);
      } else {
      println!("Command '{}' Not Recognized", input);
      shell(input, &version);
      }
      }
      Err(err) => panic!("incorrect"),
      }
      }






      rust






      share|improve this question









      New contributor




      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 39 mins ago









      Jamal

      30.3k11119227




      30.3k11119227






      New contributor




      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 5 hours ago









      rustacean_in_trainingrustacean_in_training

      61




      61




      New contributor




      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      rustacean_in_training is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          1 Answer
          1






          active

          oldest

          votes


















          0












          $begingroup$


          1. Use rustfmt. I know the code you've presented is formatted correctly now, but that's because I reformatted it for you over on Stack Overflow (I wouldn't have touched it here).



          2. Read and address the compiler's warning messages!



            warning: unused variable: `b`
            --> src/main.rs:13:12
            |
            13 | Ok(b) => {
            | ^ help: consider using `_b` instead
            |
            = note: #[warn(unused_variables)] on by default

            warning: unused variable: `err`
            --> src/main.rs:22:13
            |
            22 | Err(err) => panic!("incorrect"),
            | ^^^ help: consider using `_err` instead

            warning: function cannot return without recursing
            --> src/main.rs:10:1
            |
            10 | fn shell(input: &mut String, version: &String) {
            | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
            ...
            16 | shell(input, version);
            | --------------------- recursive call site
            ...
            19 | shell(input, &version);
            | ---------------------- recursive call site
            |
            = note: #[warn(unconditional_recursion)] on by default
            = help: a `loop` may express intention better if this is on purpose

            Finished dev [unoptimized + debuginfo] target(s) in 2.16s
            Running `target/debug/playground`


          3. Don't have infinite recursion; that's almost always a bad idea and you will run out of stack space. Write an infinite loop instead.


          4. There's no reason to put input outside of the function, as it's only ever used inside it.



          5. Use clippy. It will point out things like:



            warning: writing `&String` instead of `&str` involves a new object where a slice will do.
            --> src/main.rs:9:19
            |
            9 | fn shell(version: &String) {
            | ^^^^^^^ help: change this to: `&str`
            |
            = note: #[warn(clippy::ptr_arg)] on by default
            = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

            warning: needlessly taken reference of both operands
            --> src/main.rs:15:16
            |
            15 | if &input.trim() == &"ver" || &input.trim() == &"what are you" {
            | ^^^^^^^^^^^^^^^^^^^^^^^
            |
            = note: #[warn(clippy::op_ref)] on by default
            = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
            help: use the values directly
            |
            15 | if input.trim() == "ver" || &input.trim() == &"what are you" {
            | ^^^^^^^^^^^^ ^^^^^


            See also:




            • Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?



          6. Use Result::expect instead of doing the match yourself. This has the beenfit of printing out the underlying error message as well.


          7. Store the result of trim to avoid doing the work multiple times.


          8. Consider using a match on the trimmed string to decide what to work on.



          use std::io;

          fn main() {
          let version = "0.0.1";

          shell(version);
          }

          fn shell(version: &str) {
          let mut input = String::new();
          loop {
          input.clear();
          io::stdin().read_line(&mut input).expect("incorrect");
          let input = input.trim();

          match input {
          "ver" | "what are you" => {
          println!("C ute R ust A mateur B eginner Shell ver: {}", version)
          }
          _ => println!("Command '{}' Not Recognized", input),
          }
          }
          }


          Now we can consider how best to use enums here. An enum is good for a type that can be one of many values. You have that structure in your "command" decisions. You could create an enum from those strings:



          use std::io;

          fn main() {
          let version = "0.0.1";

          shell(version);
          }

          fn shell(version: &str) {
          let mut input = String::new();
          loop {
          input.clear();
          io::stdin().read_line(&mut input).expect("incorrect");
          let command = input.trim().parse::<Command>();

          use Command::*;
          match command {
          Ok(Version) | Ok(WhatAreYou) => {
          println!("C ute R ust A mateur B eginner Shell ver: {}", version)
          }
          Err(_) => println!("Command '{}' Not Recognized", input),
          }
          }
          }

          #[derive(Debug)]
          enum Command {
          Version,
          WhatAreYou,
          }

          impl std::str::FromStr for Command {
          type Err = ();

          fn from_str(input: &str) -> Result<Self, Self::Err> {
          use Command::*;
          Ok(match input {
          "ver" => Version,
          "what are you" => WhatAreYou,
          _ => return Err(()),
          })
          }
          }
          ```





          share|improve this answer









          $endgroup$













            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });






            rustacean_in_training is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214499%2fchecking-against-user-input-and-returns-a-response-based-on-that-input%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0












            $begingroup$


            1. Use rustfmt. I know the code you've presented is formatted correctly now, but that's because I reformatted it for you over on Stack Overflow (I wouldn't have touched it here).



            2. Read and address the compiler's warning messages!



              warning: unused variable: `b`
              --> src/main.rs:13:12
              |
              13 | Ok(b) => {
              | ^ help: consider using `_b` instead
              |
              = note: #[warn(unused_variables)] on by default

              warning: unused variable: `err`
              --> src/main.rs:22:13
              |
              22 | Err(err) => panic!("incorrect"),
              | ^^^ help: consider using `_err` instead

              warning: function cannot return without recursing
              --> src/main.rs:10:1
              |
              10 | fn shell(input: &mut String, version: &String) {
              | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
              ...
              16 | shell(input, version);
              | --------------------- recursive call site
              ...
              19 | shell(input, &version);
              | ---------------------- recursive call site
              |
              = note: #[warn(unconditional_recursion)] on by default
              = help: a `loop` may express intention better if this is on purpose

              Finished dev [unoptimized + debuginfo] target(s) in 2.16s
              Running `target/debug/playground`


            3. Don't have infinite recursion; that's almost always a bad idea and you will run out of stack space. Write an infinite loop instead.


            4. There's no reason to put input outside of the function, as it's only ever used inside it.



            5. Use clippy. It will point out things like:



              warning: writing `&String` instead of `&str` involves a new object where a slice will do.
              --> src/main.rs:9:19
              |
              9 | fn shell(version: &String) {
              | ^^^^^^^ help: change this to: `&str`
              |
              = note: #[warn(clippy::ptr_arg)] on by default
              = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

              warning: needlessly taken reference of both operands
              --> src/main.rs:15:16
              |
              15 | if &input.trim() == &"ver" || &input.trim() == &"what are you" {
              | ^^^^^^^^^^^^^^^^^^^^^^^
              |
              = note: #[warn(clippy::op_ref)] on by default
              = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
              help: use the values directly
              |
              15 | if input.trim() == "ver" || &input.trim() == &"what are you" {
              | ^^^^^^^^^^^^ ^^^^^


              See also:




              • Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?



            6. Use Result::expect instead of doing the match yourself. This has the beenfit of printing out the underlying error message as well.


            7. Store the result of trim to avoid doing the work multiple times.


            8. Consider using a match on the trimmed string to decide what to work on.



            use std::io;

            fn main() {
            let version = "0.0.1";

            shell(version);
            }

            fn shell(version: &str) {
            let mut input = String::new();
            loop {
            input.clear();
            io::stdin().read_line(&mut input).expect("incorrect");
            let input = input.trim();

            match input {
            "ver" | "what are you" => {
            println!("C ute R ust A mateur B eginner Shell ver: {}", version)
            }
            _ => println!("Command '{}' Not Recognized", input),
            }
            }
            }


            Now we can consider how best to use enums here. An enum is good for a type that can be one of many values. You have that structure in your "command" decisions. You could create an enum from those strings:



            use std::io;

            fn main() {
            let version = "0.0.1";

            shell(version);
            }

            fn shell(version: &str) {
            let mut input = String::new();
            loop {
            input.clear();
            io::stdin().read_line(&mut input).expect("incorrect");
            let command = input.trim().parse::<Command>();

            use Command::*;
            match command {
            Ok(Version) | Ok(WhatAreYou) => {
            println!("C ute R ust A mateur B eginner Shell ver: {}", version)
            }
            Err(_) => println!("Command '{}' Not Recognized", input),
            }
            }
            }

            #[derive(Debug)]
            enum Command {
            Version,
            WhatAreYou,
            }

            impl std::str::FromStr for Command {
            type Err = ();

            fn from_str(input: &str) -> Result<Self, Self::Err> {
            use Command::*;
            Ok(match input {
            "ver" => Version,
            "what are you" => WhatAreYou,
            _ => return Err(()),
            })
            }
            }
            ```





            share|improve this answer









            $endgroup$


















              0












              $begingroup$


              1. Use rustfmt. I know the code you've presented is formatted correctly now, but that's because I reformatted it for you over on Stack Overflow (I wouldn't have touched it here).



              2. Read and address the compiler's warning messages!



                warning: unused variable: `b`
                --> src/main.rs:13:12
                |
                13 | Ok(b) => {
                | ^ help: consider using `_b` instead
                |
                = note: #[warn(unused_variables)] on by default

                warning: unused variable: `err`
                --> src/main.rs:22:13
                |
                22 | Err(err) => panic!("incorrect"),
                | ^^^ help: consider using `_err` instead

                warning: function cannot return without recursing
                --> src/main.rs:10:1
                |
                10 | fn shell(input: &mut String, version: &String) {
                | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
                ...
                16 | shell(input, version);
                | --------------------- recursive call site
                ...
                19 | shell(input, &version);
                | ---------------------- recursive call site
                |
                = note: #[warn(unconditional_recursion)] on by default
                = help: a `loop` may express intention better if this is on purpose

                Finished dev [unoptimized + debuginfo] target(s) in 2.16s
                Running `target/debug/playground`


              3. Don't have infinite recursion; that's almost always a bad idea and you will run out of stack space. Write an infinite loop instead.


              4. There's no reason to put input outside of the function, as it's only ever used inside it.



              5. Use clippy. It will point out things like:



                warning: writing `&String` instead of `&str` involves a new object where a slice will do.
                --> src/main.rs:9:19
                |
                9 | fn shell(version: &String) {
                | ^^^^^^^ help: change this to: `&str`
                |
                = note: #[warn(clippy::ptr_arg)] on by default
                = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

                warning: needlessly taken reference of both operands
                --> src/main.rs:15:16
                |
                15 | if &input.trim() == &"ver" || &input.trim() == &"what are you" {
                | ^^^^^^^^^^^^^^^^^^^^^^^
                |
                = note: #[warn(clippy::op_ref)] on by default
                = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
                help: use the values directly
                |
                15 | if input.trim() == "ver" || &input.trim() == &"what are you" {
                | ^^^^^^^^^^^^ ^^^^^


                See also:




                • Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?



              6. Use Result::expect instead of doing the match yourself. This has the beenfit of printing out the underlying error message as well.


              7. Store the result of trim to avoid doing the work multiple times.


              8. Consider using a match on the trimmed string to decide what to work on.



              use std::io;

              fn main() {
              let version = "0.0.1";

              shell(version);
              }

              fn shell(version: &str) {
              let mut input = String::new();
              loop {
              input.clear();
              io::stdin().read_line(&mut input).expect("incorrect");
              let input = input.trim();

              match input {
              "ver" | "what are you" => {
              println!("C ute R ust A mateur B eginner Shell ver: {}", version)
              }
              _ => println!("Command '{}' Not Recognized", input),
              }
              }
              }


              Now we can consider how best to use enums here. An enum is good for a type that can be one of many values. You have that structure in your "command" decisions. You could create an enum from those strings:



              use std::io;

              fn main() {
              let version = "0.0.1";

              shell(version);
              }

              fn shell(version: &str) {
              let mut input = String::new();
              loop {
              input.clear();
              io::stdin().read_line(&mut input).expect("incorrect");
              let command = input.trim().parse::<Command>();

              use Command::*;
              match command {
              Ok(Version) | Ok(WhatAreYou) => {
              println!("C ute R ust A mateur B eginner Shell ver: {}", version)
              }
              Err(_) => println!("Command '{}' Not Recognized", input),
              }
              }
              }

              #[derive(Debug)]
              enum Command {
              Version,
              WhatAreYou,
              }

              impl std::str::FromStr for Command {
              type Err = ();

              fn from_str(input: &str) -> Result<Self, Self::Err> {
              use Command::*;
              Ok(match input {
              "ver" => Version,
              "what are you" => WhatAreYou,
              _ => return Err(()),
              })
              }
              }
              ```





              share|improve this answer









              $endgroup$
















                0












                0








                0





                $begingroup$


                1. Use rustfmt. I know the code you've presented is formatted correctly now, but that's because I reformatted it for you over on Stack Overflow (I wouldn't have touched it here).



                2. Read and address the compiler's warning messages!



                  warning: unused variable: `b`
                  --> src/main.rs:13:12
                  |
                  13 | Ok(b) => {
                  | ^ help: consider using `_b` instead
                  |
                  = note: #[warn(unused_variables)] on by default

                  warning: unused variable: `err`
                  --> src/main.rs:22:13
                  |
                  22 | Err(err) => panic!("incorrect"),
                  | ^^^ help: consider using `_err` instead

                  warning: function cannot return without recursing
                  --> src/main.rs:10:1
                  |
                  10 | fn shell(input: &mut String, version: &String) {
                  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
                  ...
                  16 | shell(input, version);
                  | --------------------- recursive call site
                  ...
                  19 | shell(input, &version);
                  | ---------------------- recursive call site
                  |
                  = note: #[warn(unconditional_recursion)] on by default
                  = help: a `loop` may express intention better if this is on purpose

                  Finished dev [unoptimized + debuginfo] target(s) in 2.16s
                  Running `target/debug/playground`


                3. Don't have infinite recursion; that's almost always a bad idea and you will run out of stack space. Write an infinite loop instead.


                4. There's no reason to put input outside of the function, as it's only ever used inside it.



                5. Use clippy. It will point out things like:



                  warning: writing `&String` instead of `&str` involves a new object where a slice will do.
                  --> src/main.rs:9:19
                  |
                  9 | fn shell(version: &String) {
                  | ^^^^^^^ help: change this to: `&str`
                  |
                  = note: #[warn(clippy::ptr_arg)] on by default
                  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

                  warning: needlessly taken reference of both operands
                  --> src/main.rs:15:16
                  |
                  15 | if &input.trim() == &"ver" || &input.trim() == &"what are you" {
                  | ^^^^^^^^^^^^^^^^^^^^^^^
                  |
                  = note: #[warn(clippy::op_ref)] on by default
                  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
                  help: use the values directly
                  |
                  15 | if input.trim() == "ver" || &input.trim() == &"what are you" {
                  | ^^^^^^^^^^^^ ^^^^^


                  See also:




                  • Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?



                6. Use Result::expect instead of doing the match yourself. This has the beenfit of printing out the underlying error message as well.


                7. Store the result of trim to avoid doing the work multiple times.


                8. Consider using a match on the trimmed string to decide what to work on.



                use std::io;

                fn main() {
                let version = "0.0.1";

                shell(version);
                }

                fn shell(version: &str) {
                let mut input = String::new();
                loop {
                input.clear();
                io::stdin().read_line(&mut input).expect("incorrect");
                let input = input.trim();

                match input {
                "ver" | "what are you" => {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version)
                }
                _ => println!("Command '{}' Not Recognized", input),
                }
                }
                }


                Now we can consider how best to use enums here. An enum is good for a type that can be one of many values. You have that structure in your "command" decisions. You could create an enum from those strings:



                use std::io;

                fn main() {
                let version = "0.0.1";

                shell(version);
                }

                fn shell(version: &str) {
                let mut input = String::new();
                loop {
                input.clear();
                io::stdin().read_line(&mut input).expect("incorrect");
                let command = input.trim().parse::<Command>();

                use Command::*;
                match command {
                Ok(Version) | Ok(WhatAreYou) => {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version)
                }
                Err(_) => println!("Command '{}' Not Recognized", input),
                }
                }
                }

                #[derive(Debug)]
                enum Command {
                Version,
                WhatAreYou,
                }

                impl std::str::FromStr for Command {
                type Err = ();

                fn from_str(input: &str) -> Result<Self, Self::Err> {
                use Command::*;
                Ok(match input {
                "ver" => Version,
                "what are you" => WhatAreYou,
                _ => return Err(()),
                })
                }
                }
                ```





                share|improve this answer









                $endgroup$




                1. Use rustfmt. I know the code you've presented is formatted correctly now, but that's because I reformatted it for you over on Stack Overflow (I wouldn't have touched it here).



                2. Read and address the compiler's warning messages!



                  warning: unused variable: `b`
                  --> src/main.rs:13:12
                  |
                  13 | Ok(b) => {
                  | ^ help: consider using `_b` instead
                  |
                  = note: #[warn(unused_variables)] on by default

                  warning: unused variable: `err`
                  --> src/main.rs:22:13
                  |
                  22 | Err(err) => panic!("incorrect"),
                  | ^^^ help: consider using `_err` instead

                  warning: function cannot return without recursing
                  --> src/main.rs:10:1
                  |
                  10 | fn shell(input: &mut String, version: &String) {
                  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
                  ...
                  16 | shell(input, version);
                  | --------------------- recursive call site
                  ...
                  19 | shell(input, &version);
                  | ---------------------- recursive call site
                  |
                  = note: #[warn(unconditional_recursion)] on by default
                  = help: a `loop` may express intention better if this is on purpose

                  Finished dev [unoptimized + debuginfo] target(s) in 2.16s
                  Running `target/debug/playground`


                3. Don't have infinite recursion; that's almost always a bad idea and you will run out of stack space. Write an infinite loop instead.


                4. There's no reason to put input outside of the function, as it's only ever used inside it.



                5. Use clippy. It will point out things like:



                  warning: writing `&String` instead of `&str` involves a new object where a slice will do.
                  --> src/main.rs:9:19
                  |
                  9 | fn shell(version: &String) {
                  | ^^^^^^^ help: change this to: `&str`
                  |
                  = note: #[warn(clippy::ptr_arg)] on by default
                  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg

                  warning: needlessly taken reference of both operands
                  --> src/main.rs:15:16
                  |
                  15 | if &input.trim() == &"ver" || &input.trim() == &"what are you" {
                  | ^^^^^^^^^^^^^^^^^^^^^^^
                  |
                  = note: #[warn(clippy::op_ref)] on by default
                  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
                  help: use the values directly
                  |
                  15 | if input.trim() == "ver" || &input.trim() == &"what are you" {
                  | ^^^^^^^^^^^^ ^^^^^


                  See also:




                  • Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?



                6. Use Result::expect instead of doing the match yourself. This has the beenfit of printing out the underlying error message as well.


                7. Store the result of trim to avoid doing the work multiple times.


                8. Consider using a match on the trimmed string to decide what to work on.



                use std::io;

                fn main() {
                let version = "0.0.1";

                shell(version);
                }

                fn shell(version: &str) {
                let mut input = String::new();
                loop {
                input.clear();
                io::stdin().read_line(&mut input).expect("incorrect");
                let input = input.trim();

                match input {
                "ver" | "what are you" => {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version)
                }
                _ => println!("Command '{}' Not Recognized", input),
                }
                }
                }


                Now we can consider how best to use enums here. An enum is good for a type that can be one of many values. You have that structure in your "command" decisions. You could create an enum from those strings:



                use std::io;

                fn main() {
                let version = "0.0.1";

                shell(version);
                }

                fn shell(version: &str) {
                let mut input = String::new();
                loop {
                input.clear();
                io::stdin().read_line(&mut input).expect("incorrect");
                let command = input.trim().parse::<Command>();

                use Command::*;
                match command {
                Ok(Version) | Ok(WhatAreYou) => {
                println!("C ute R ust A mateur B eginner Shell ver: {}", version)
                }
                Err(_) => println!("Command '{}' Not Recognized", input),
                }
                }
                }

                #[derive(Debug)]
                enum Command {
                Version,
                WhatAreYou,
                }

                impl std::str::FromStr for Command {
                type Err = ();

                fn from_str(input: &str) -> Result<Self, Self::Err> {
                use Command::*;
                Ok(match input {
                "ver" => Version,
                "what are you" => WhatAreYou,
                _ => return Err(()),
                })
                }
                }
                ```






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 1 hour ago









                ShepmasterShepmaster

                7,0831219




                7,0831219






















                    rustacean_in_training is a new contributor. Be nice, and check out our Code of Conduct.










                    draft saved

                    draft discarded


















                    rustacean_in_training is a new contributor. Be nice, and check out our Code of Conduct.













                    rustacean_in_training is a new contributor. Be nice, and check out our Code of Conduct.












                    rustacean_in_training is a new contributor. Be nice, and check out our Code of Conduct.
















                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214499%2fchecking-against-user-input-and-returns-a-response-based-on-that-input%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                    is 'sed' thread safe

                    How to make a Squid Proxy server?