We are getting somewhere! But this feels really verbose. Is there some kind of derive macro in std or some crate that would generate the fn new(...)? Something like this:
So my question then is: For such a trivially simple struct why bother with implementing "new" for it at all? Just create them in place like my n2 above.
Hi,
well the thing is, that your second solution only works if you have the definition of the struct and the "instantiation" in the same module. If this is not the case the compiler will complain at your second example, that id is a private field, hence you'd need a new constructor for this:
This is indeed a good thing (otherwise you couldn't enforce invariant in the constructor if users could "just" create the object without using the constructors.
This means that my initial question is still valid. Is there a way to auto-generate the new() function?
You can use something like derive-new to generate a new() static method. The derive-more crate also has #[derive]'s for converting to/from other types when the conversion is trivial, as well as its own #[derive] for generating a constructor.
I'd be tempted to ask whether you actually need this in the first place, though...
If you're generating a function which takes as many arguments as your struct has fields and will just populate those fields, why not drop the constructor, make the fields public, and let callers create the object themselves? Auto-generated constructors don't actually help, because the moment you add a new private field the constructor will get a new argument and you'll break all downstream users.
To create an instance of some type, you just need to write the object literal (e.g. Node(42) for your newtype struct, or Node { id: 42 } for a struct with named fields). Unlike languages with inheritance (C++, Python, Java, etc.) the constructor isn't special, it's just a name we use for some function that creates a new instance of something.
This is incorrect. Non-public fields are only accessible within the module they are defined in. It sounds like you might need to check out the Defining Modules to Control Scope and Privacy chapter from The Rust Programming Language.
I am manipulating a graph, and I need to make the difference between crossroad (that are connected to 3 or more points), dead-end (that are connected to 0 or 1 point), and waypoints (that are connected to exactly 2 other points, those points draws the curve of a road). I want to enforce those properties at compile time.
Because I don't want the fields to be writable once created (they can be copied, but not modified).
I was just highly confused when I read ZiCog's answer. I was obviously already using this syntax in my constructors, but the way he phrased it made me thing that it was also possible to use it anywhere (A bit like Foo{1, 2} in C++). And my stupid brain thought that it was something new that I never saw.
I want to mention that this is only half true. Non-public fields are only accessible within the module they are defined in and in the module's childs.
Which means we can separate some implementation blocks into child modules, e.g.:
mod a {
#[derive(Debug)]
pub struct A { id: usize }
mod b {
use super::A;
impl A {
pub fn new() -> Self {
A { id: 42 }
}
}
}
}
fn main() {
let a = a::A::new();
println!("This is a: {:?}", a);
// Fails because `id` is private
// println!("This is a.id: {:?}", a.id);
}