Is there a faster/shorter way to initialize variables in a Rust struct?
In the following example, I would much prefer to assign a value to each field in the struct in the declaration of the fields. Alternatively, it effectively takes one additional statement for each field to assign a value to the fields. All I want to be able to do is to assign default values when the struct is instantiated.
Is there a more succinct way of doing this?
struct cParams {
iInsertMax: i64,
iUpdateMax: i64,
iDeleteMax: i64,
iInstanceMax: i64,
tFirstInstance: bool,
tCreateTables: bool,
tContinue: bool,
}
impl cParams {
fn new() -> cParams {
cParams {
iInsertMax: -1,
iUpdateMax: -1,
iDeleteMax: -1,
iInstanceMax: -1,
tFirstInstance: false,
tCreateTables: false,
tContinue: false,
}
}
}
Solution 1:
You can provide default values for your struct by implementing the Default
trait. The default
function would look like your current new
function:
impl Default for cParams {
fn default() -> cParams {
cParams {
iInsertMax: -1,
iUpdateMax: -1,
iDeleteMax: -1,
iInstanceMax: -1,
tFirstInstance: false,
tCreateTables: false,
tContinue: false,
}
}
}
You can then instantiate the struct by giving only the non-default values:
let p = cParams { iInsertMax: 10, ..Default::default() };
With some minor changes to your data structure, you can take advantage of an automatically derived default implementation. If you use #[derive(Default)]
on a data structure, the compiler will automatically create a default function for you that fills each field with its default value. The default boolean value is false, the default integral value is 0.
An integer's default value being 0 is a problem here since you want the integer fields to be -1 by default. You could define a new type that implements a default value of -1 and use that instead of i64
in your struct. (I haven't tested that, but it should work).
However, I'd suggest to slightly change your data structure and use Option<i64>
instead of i64
. I don't know the context of your code, but it looks like you're using the special value of -1 to represent the special meaning "infinite", or "there's no max". In Rust, we use an Option
to represent an optionally present value. There's no need for a -1 hack. An option can be either None
or Some(x)
where x would be your i64
here. It might even be an unsigned integer if -1 was the only negative value. The default Option
value is None
, so with the proposed changes, your code could look like this:
#[derive(Default)]
struct cParams {
iInsertMax: Option<u64>,
iUpdateMax: Option<u64>,
iDeleteMax: Option<u64>,
iInstanceMax: Option<u64>,
tFirstInstance: bool,
tCreateTables: bool,
tContinue: bool,
}
let p = cParams { iInsertMax: Some(10), ..Default::default() };
Solution 2:
nowadays, it is possible to do exactly what OP was asking 8 years ago
to assign a value to each field in the struct in the declaration of the fields.
using derivative crate:
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Debug, Default)]
struct cParams {
#[derivative(Default(value = "-1"))]
iInsertMax: i64,
#[derivative(Default(value = "-1"))]
iUpdateMax: i64,
#[derivative(Default(value = "-1"))]
iDeleteMax: i64,
#[derivative(Default(value = "-1"))]
iInstanceMax: i64,
#[derivative(Default(value = "false"))]
tFirstInstance: bool,
#[derivative(Default(value = "false"))]
tCreateTables: bool,
#[derivative(Default(value = "false"))]
tContinue: bool,
}
fn main() {
println!("cParams: {:?}", cParams::default());
}
Also, it is not necessary to define default falsy values for booleans in this way because Default
will set them to this value anyway