3 ms·
> If you don't provide an initializer, the compiler inserts the default initializer for it. This requires that there is a default. Several modern languages (su
by tialaramex 7mo ago
> If you don't provide an initializer, the compiler inserts the default initializer for it.
This requires that there is a default. Several modern languages (such as Go) insist on this, it means now your types don't even model reality in this very fundamental way. Who is a person's default spouse? Even where you can imagine a default it's sometimes undesirable to have one, for example we already live in a society where somebody decided default gender is male - and it might look too much like real data, default birthday being 1 January also matches hundreds of thousands of Americans...
The most likely place you go after "Everything has a default" is the billion dollar mistake because you're inclined to just incorporate "or it's default invalid" into the type definition to get your default, and when you do that everywhere needs to have "check it's valid" code added, even if we already just checked that a moment ago.
- kwsp 7mo agoI don’t care that much about everything having a default (although it’s nice), but if a language insists on a default value for every type for safety, can’t you just use std::optional?
- tialaramex 7mo agoI can't tell if you imagine std::optional is a value (it is not) or if you know it's a templated type but you imagine that somehow it would be OK to redefine all programs so that every type is std::optional<T> of that type instead so as to simplify initialization. Either way no, that can't work.
- MaxBarraclough 7mo ago> Either way no, that can't work. Kotlin has explicit nullable types. Rust has no null, but has option types. Both languages work fine. I think your point was that neither approach could reasonably be retrofitted to C++, do I have that right?
- tialaramex 7mo agoRust works fine because types are not required to have a default, if you want your type to have a default you implement Rust's Default trait. Stuff which only makes sense if there's a default just depends on that trait and so won't be available, for example you can't core::mem::take your custom Goose type which has no default because core::mem::take<T: Default>. In Rust if we say there's a variable of type Goose and don't initialize it, it's not initialized, and if the compiler can't see why it's initialized before it's used the program is rejected as nonsense because Rust is a safe language and that's an unsafe outcome. I don't write Kotlin, so I can't speak to the details there. C++ like Rust does not require that types have a default. In C++ the way you provide a "default" is usually via a zero argument constructor, since the compiler can just call that wherever you asked for an instance of that type and there's no requirement to write such a constructor, or indeed to provide any public constructor at all. So "just use the default" could not work in C++ as it exists today yes. The other reason C++ can't do anything like this is that it makes a newer C++ with this behaviour behave differently despite no syntactical change. Rust is OK with that, because it has the Edition system to differentiate Rust 2015 code which means one thing from Rust 2024 code which means something else despite having the same text, but in C++ they do not have anything like that, it's not rare for somebody's C++ 17 code to get compiled in C++ 23 and people expect that to work (it doesn't always work but that's what they expect).
- inetknght 7mo agoI often see arguments like yours. I reject them wholeheartedly. Your argument is pro-poor-design. I tell you: design your software better. Design your software so that you can't have undefined behavior. It's harder, yes. LLMs suck at it, yes. But building well-designed software is a significant part of being a better engineer.
- steveklabnik 7mo agoIt is easier to design the software so that you don't have confusing behavior when you're not required to include behaviors you don't want. Most things do not need to be nullable. Requiring all things to have a zero value, even when they do not have one, makes it harder to be correct by construction, not easier.
- WalterBright 7mo ago> Requiring all things to have a zero value D default initializes floats to NaN.
- inetknght 7mo ago> It is easier to design the software so that you don't have confusing behavior when you're not required to include behaviors you don't want. It can be easier, but not always. But it is almost always a better design. Redesigning software so that whole classes of problems simply can't exist is absolutely better than software that needs to handle all kinds of problems. Many of those problems might not even ever happen in real circumstances! > Requiring all things to have a zero value, even when they do not have one, makes it harder to be correct by construction, not easier. Don't require a "zero value". Require a "correctly-constructed" value. Sometimes zero is correctly constructed, sometimes not.
- steveklabnik 7mo agoI agree that you want to require a correctly-constructed value. The entire point I'm making is that in languages with zero values, this is hard, because that zero value may not be valid for your domain. Languages with pervasive nullability effectively gives everything a zero value.