It's basically mandating Rust's Default trait or the C++ default (no argument) constructor. In some places you can live with a Default but you wish there wasn't one. Default Gender = Male is... not great, but we can live with it, some natural languages work like this, and there are problems but they're not insurmountable. Default Date of Birth is... 1 January 1970 ? 1 January 1900? 0AD ? Also not a good idea but if you insist.
But in other places there just is no sane Default. So you're forced to create a dummy state, recapitulating the NULL problem but for a brand new type. Default file descriptor? No. OK, here's a "file descriptor" that's in a permanent error state, is that OK? All of my code will need to special case this, what a disaster.
enum Gender {
Unspecified,
Male,
Female,
Other,
}
impl Default for Gender {
default() -> Self {
Self::Unspecified
}
}
or: enum Gender {
Male,
Female,
Other,
}
and use Option<Gender> instead of Gender directly, with Option::None here meaning the same that we would mean by Gender::Unspecified(Sometimes your domain type really does have a suitable natural default value, and you just make that the zero value.)
> All of my code will need to special case this, what a disaster.
No, your code should handle the error state first and treat the value as invalid up until that point, e.g.
foo, err := getVal()
if err != nil {
return
}
// foo can only be used now
It's infuriating that there's no compiler support to make this easier, but c'est la vie.