Idiomatic initialization of unset struct fields

Hi,
What es the idiomatic way of setting a variable to an unset value?
I started by writing the folowing struct:

struct BlastJob {
    send_job_url: String,
    rid: Option<String>,
    rtoe: Option<Duration>,
    last_access: Option<SystemTime>
}

I have a BlastJob::new() method that fills send_job_url and set the other fields to None.

BlastJob {
    send_job_url,
    rid: None,
    rtoe: None,
    last_access: None,
}

Then there is a BlastJob::launch() method the unconditionally fills the last three fields and other methods write and read them, but if course I have to wrap and unwrap the values.
Would it be too unidiomatic (or may be the right form?) to declare de struct as:

struct BlastJob {
    send_job_url: String,
    rid: String,
    rtoe: Duration,
    last_access: SystemTime,
}

and initaliize with:

BlastJob {
    send_job_url,
    rid: String::new(),
    rtoe: Duration::ZERO,
    last_access: SystemTime::UNIX_EPOCH,
}

knowing that these values mean "unset"?.

Thanks!

Rust has a concept of a Default value. You can implement Default trait for a struct, and then create an object with Default::default(), and also use it to fill in rest of the fields using .. struct operator.

Thanks for the reply.

Yes, I can implement Default and let BlastJob::new() return
SomeOptions { send_job_url, ..Default::default() }

But my dilemma stays the same. Is it OK to use an empty string or a 0 to signal unset? Naturally I have to assure that the empty string or 0 have no other meaning that "unset".
The code will work either way, and this is a small self contained program so I'm comfortable storing the two concepts in a non Option variable (the value itself and whether it is something or not (Yes, for that reason we have Option::Some() and Option::None))
I just wondered if such code is an eyesore for a seasoned Rustician.

To be honest, the most idiomatic thing in Rust is to not have an unset variable.

Instead, you should only create the BlastJob once all of its constituent parts have been created. That way you can always assume that the BlastJob is ready to be used and in a valid state, instead of being in a kinda-sorta-initialized intermediate state like you get in object constructors for OO languages.

You may want to look into the builder pattern where you have a builder type with a lot of Option fields, and then some way to convert that into your BlastJob with no Options wherein you know the fields have been set. There will be various considerations depending on your use case; it may or may not be a good fit depending on how exactly launch works in your case, for example.

Thaks. I made BlastJob an enum with the diferent job states as variants, each one with only the atributes that are valid at that stage.

1 Like