Ad
  • Default User Avatar

    I missed to speak about Person::greet. No more sentences, just code:

    fn greet(&self) -> String {
        let start = "Hello, my name is ";
        if self.last_name.len() > 0 {
            format!("{}{} {}", start, self.first_name, self.last_name)
        } else {
            format!("{}{}", start, self.first_name)
        }
    }
    

    Full code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6f5a936cd0482aceb70bb839fceb433c

    EDIT: I would have optimized by implementing std::fmt::Display.

  • Default User Avatar

    This is a macro, not a function, so you just remade my code as a function.

    I just applied most of my suggestions to made them more clear. I also missed detail about using standard traits. It offers you a lot of advantage thank to generic implementation, you benefit from other traits that have generic implemention over implemented traits.

    For example by implementing std::default:Default, you are able to create default std::option::Option.

    Such std::convert::TryFrom would be better than std::str::FromStr !

    Tell me how to fix the macro if you need to correct me.

    If this is just a "macro-to-function" transformation, you will surely be able to do.

    Next time when displaying code in markdown do this:

    Sorry, long time I haven't post on Codewars. I was just hoping auto-detection due to context and content (just as most services do)

    Now tell me why you used &str

    &str are slices (looks like a "partial" burrow over piece of data). They avoid memory duplication & ownership. It also lets you abstract over &'static str and String burrows.

    Now tell me when you used if

    As it was specified: two-way alternatives. To be honest, you should be able to directly pattern match over the array names.


    Here we go:

    macro_rules! createPerson {
        ($name: expr) => {
            {
                let names = $name
                    .split(' ')
                    .collect::<Vec<&str>>();
                
                let (first_name, last_name) = match &names[..] {
                    &[first]       => (first, ""),
                    &[first, last] => (first, last),
                    _              => panic!("Entered wrong amount of words"),
                };
                Person::new(first_name.to_string(), last_name.to_string())
            }
        };
        ($fname: expr, $lname: expr) => {
            Person::new($fname, $lname)
        }
    }
    
  • Custom User Avatar
    • This is a macro, not a function, so you just remade my code as a function.
    • Tell me how to fix the macro if you need to correct me.
    • Next time when displaying code in markdown do this:
    • ```rust <code> ```
    • Now tell me why you used &str and when you used if.
  • Default User Avatar
    1. In createPerson avoid creating a "default" instance that NEVER be used.
    2. May be add a slice-based (&str) constructor
    3. if are expressions, use it :)
    4. if may alternate on constructor parameters that each calling constructor
    5. std::str::FromStr sounds better
    impl FromStr for Person {
        type Err = String;
        
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let names = s
                    .split(' ')
                    .collect::<Vec<&str>>();
            
            let (first_name, last_name) = match names.len() {
                1 => (names[0], ""),
                2 => (names[0], names[1]),
                _ => Err("Invalid word count".to_string())?
            };
            Ok(Self::new(first_name.to_string(), last_name.to_string()))
        }
    }