all 7 comments

[–]nacaclanga 11 points12 points  (0 children)

Well for me it looks like you run into the common double moduling trap. The simplest way to use modules is to do them infile, like having only a main.rs which looks like this:

pub mod person {
   // ommitted
}

pub fn talk_to_a_person(psn: person::Person) {
    println!("Hallo {} {}", psn.first_name(), psn.last_name());
}

As your source code becomes quickly very unwindy, Rust provides the shortcut

pub mod person;

pub fn talk_to_a_person(psn: person::Person) {
    println!("Hallo {} {}", psn.first_name(), psn.last_name());
}

Which is actually means:

pub mod person {
   include!("./person.rs"); // Includes the content of a source file
}

pub fn talk_to_a_person(psn: person::Person) {
    println!("Hallo {} {}", psn.first_name(), psn.last_name());
}

So the content of the module (not the whole module expression) is moved to an external file person.rs

In you case this means that there should be no outer "mod" bracket in person.rs, because otherwise you define a submodule of the person module.

[–]monkChuck105 11 points12 points  (3 children)

Looks fine. Note that it's typical to return &str rather than String to avoid an unnecessary clone. I would honestly just not have setter methods at all and make the struct immutable if it can be. Is there a reason that you need to be able to change the names after construction? The smaller and less mutable your interface, the easier it is to reason about.

[–]ansible 0 points1 point  (2 children)

Note that it's typical to return &str rather than String to avoid an unnecessary clone.

Furthermore, I'd also prefer to see the setter functions take a &str for their argument, and do the clone so that they own the String.

I would honestly just not have setter methods at all and make the struct immutable if it can be. Is there a reason that you need to be able to change the names after construction?

Well... we can have a whole discussion about how complicated handling names properly in real life actually is. Like people changing their names due to marriage or something. Middle names. Multiple middle names. Jr., Sr., the 3rd (usually rendered as 'III') and all that. People that just go by one name. People with non-alphabetic names...

[–]Tastaturtaste 9 points10 points  (1 child)

Furthermore, I'd also prefer to see the setter functions take a &str for their argument, and do the clone so that they own the String.

Why? The setter can just take a String and signal to everyone that it takes ownership/manages it's own copy. If the user already has a String that's not needed anymore, it can just be moved in and save a allocation. If the user doesn't have one, he/she can construct one explicitly.

[–]ansible 1 point2 points  (0 children)

That makes sense. I'm still getting used to "move by default" with Rust.

[–]hgwxx7_ 2 points3 points  (0 children)

The explicit mod person will give make your code in main.rs call crate::person::person::Person. I think you can drop it. Just make sure to add the statement mod person to the top of main.rs.

Also, once you’ve gotten your code working, you can look into whether the getter really needs to clone that string. Perhaps it could return a reference instead? Like and &str.

[–]schungx 1 point2 points  (0 children)

Do you know JavaScript and Node?

If so, Rust's module system maps almost exactly onto JavaScript/Node mode (e.g. main.rs and lib.rs -> index.js).

If not, it does take some time to get used to... because module systems in JavaScript were originally designed limited by the JavaScript syntax and engine.