Jump to page: 1 2
Thread overview
Default initialization no longer a thing
Oct 23, 2023
IGotD-
Oct 23, 2023
matheus
Oct 23, 2023
IGotD-
Oct 23, 2023
claptrap
Oct 23, 2023
IGotD-
Oct 23, 2023
Jonathan M Davis
Oct 23, 2023
Paul Backus
Oct 24, 2023
deadalnix
Oct 24, 2023
zjh
Oct 24, 2023
Guillaume Piolat
Oct 24, 2023
Hipreme
Oct 24, 2023
bachmeier
Oct 24, 2023
Salih Dincer
Oct 24, 2023
Julian Fondren
Oct 24, 2023
Julian Fondren
October 23, 2023

I've recently seen that modern program languages are going away from default initialization. D early recognized no initialization being one of the many flaws in C/C++ and added default initialization which greatly improved stability which has been the standard for many languages since. C++ "fixed" this very recently but really not.

Now even more modern languages are going away from default initialization as some claim that default initialization was a source of bugs. The implementation might differ, some must give a variable a value at declaration others detect use before assign.

What is your take on this and if D would ever be modernized, is this something that D should consider?

October 23, 2023
On Monday, 23 October 2023 at 18:54:45 UTC, IGotD- wrote:
> ...
> Now even more modern languages are going away from default ...

Could you please share a few examplesnames of these modern languages?

By the way I have mixed feelings abouts this subject, I read pro/con about this, but I really think "DI" is not going to fix much of the problem.

Matheus.
October 23, 2023
On Monday, 23 October 2023 at 19:15:29 UTC, matheus wrote:
> Could you please share a few examplesnames of these modern languages?
>

Swift and Dart for example.

October 23, 2023

On Monday, 23 October 2023 at 18:54:45 UTC, IGotD- wrote:

>

Now even more modern languages are going away from default initialization as some claim that default initialization was a source of bugs. The implementation might differ, some must give a variable a value at declaration others detect use before assign.

The bug is using a variable before it has been assigned the correct value. Default initialisation doesn't solve that problem, only makes the side effects less onerous. Less likely to give weird results.

If you have a variable that needs to be initialised via a large switch, you declare it up front, and it is set in the switch. It would be more useful to know if you forgot to set it in one of the case statements that it would be to have it default initialised to zero or be told it needs to be initialised at the declaration.

But tracking the use of uninitialized variables like that is probably pretty difficult / expensive for the compiler.

October 23, 2023

On Monday, 23 October 2023 at 20:34:31 UTC, claptrap wrote:

>

But tracking the use of uninitialized variables like that is probably pretty difficult / expensive for the compiler.

Not sure if computers have become fast enough so that we can do this without compile times becoming insanely slow have anything to do with it. Imagine a Rust compiler running on 16MHz 386 during the 80s.

October 23, 2023
On Monday, October 23, 2023 12:54:45 PM MDT IGotD- via Digitalmars-d wrote:
> I've recently seen that modern program languages are going away from default initialization. D early recognized no initialization being one of the many flaws in C/C++ and added default initialization which greatly improved stability which has been the standard for many languages since. C++ "fixed" this very recently but really not.
>
> Now even more modern languages are going away from default initialization as some claim that default initialization was a source of bugs. The implementation might differ, some must give a variable a value at declaration others detect use before assign.
>
> What is your take on this and if D would ever be modernized, is this something that D should consider?

Default initialization is too baked into D for it to change at this point, and there are features that we have which you can't have without it (at least not without having objects being garbage, because they haven't been given a value yet). It's why disabling default initialization on structs can be quite annoying, since it results in them not working in a number of places (particularly with regards to arrays).

In general though, if you want to avoid issues with objects being used before they're properly initialized, you have two options:

1. Have default initialization so that it's guaranteed that the object will have a value even if it's ever used before it has the value that you want it to actually have.

2. Make the compiler smart enough to catch when a variable is used before it's initialized and make it an error, thereby forcing explicit initialization of all variables before they're used.

The second approach works in a number of cases, but inevitably, the compiler is not smart enough to correctly determine whether a variable has actually been initialized in all cases, forcing you to give it a value when it shouldn't be necessary (this is something that can happen in Java quite easily). And it's _not_ something that is actually fully solvable, because it's possible that whether a variable has been initialized yet or not depends on runtime logic which is affected by stuff outside of that function, which the programmer is aware of, but the compiler can't be due to separate compilation (though arguably, if the logic is separated enough from the variable's initialization, it should be given a value regardless just to be safe, since the other code could change without the variable's initialization code being altered appropriately).

It becomes easier for the compiler if you simply require that the variable be given a value when it's declared, but that arguably just makes the problem worse, because then you're forced to give the variable a value before you want to in any situation where you need to declare it before giving it the actual value that you want to give it. And ultimately, it results in the programmer manually doing what default initialization would have done and give the variable a value that they don't actually want to use but which will at least not be garbage.

However, arguably, an even bigger issue is initialization that doesn't necessarily involve a variable. For instance, you could have something like

auto arr = new int[](10);

or

foo(new int[](10));

In D, all of the array's elements are default-initialized to the init value of the element type, so no garbage is involved, but what if you had no default initialization? You'd be forced to do something like

auto arr = new int[](10, value);

and set all of the elements in the array to some programmer-provided value,
which really isn't any better than using a default value and might even
be less efficient given that the compiler knows the type's init value at
compile time, but it wouldn't know what the value would be if it's provided
at runtime.

Various other aspects of arrays also depend on the default value and really can't be done without it. E.G.

arr.length += 20;

isn't going to work without a default value. Without that, you'd be forced to append or use a different syntax that provided your own value to use as the default before you go and assign it what you actually want it to be later.

Default values also make implementing the logic in user-defined types easier and safer (especially in classes with inheritance), because the compiler can rely on everything having an actual value before the constructors run. Having something like immutable does actually force you to implement a lot of the same logic that you'd have to have without default initialization, so D can't simplify how constructors work with regards to code flow analysis quite as much as might be nice, but a language without immutable or const could forgo a lot of the code flow analysis that languages typically have to do for constructors in the face of inheritance, because it could know that the member variables wouldn't be garbage. With D, the compiler knows that they're not garbage but has to make sure that it doesn't reassign values to any const or immutable member variables.

There are certainly cases where default-initialized objects can be a problem (e.g. when you end up with a null pointer or reference), and in some cases, having default values can be problematic (which is why the ability disable default initialization was added to structs in D), so there's certainly an argument for requiring initialization in some cases rather than relying on a default value, but in general, having default values for all types is far more flexible than requiring that the compiler track whether a variable is initialized before it's used. So, I think that D made the right choice, but it's not particularly surprising if a number of the newer languages out there have made a different choice.

Ultimately though, I don't think that it's possible to prevent bugs with regards to initializing variables with default values that shouldn't actually be used, because even if you don't have default values in the language, there will always be cases where programmers have to give a variable a default value of some kind anyway, because the compiler can't always correctly determine whether a variable is used before it's initialized if it allows deferring initialization (and if it doesn't allow defering initialization, then you'll end up with user-decided default values that much more frequently).

- Jonathan M Davis



October 23, 2023

On Monday, 23 October 2023 at 18:54:45 UTC, IGotD- wrote:

>

What is your take on this and if D would ever be modernized, is this something that D should consider?

Most of the time, default initialization is what you want, and it doesn't cause any problems. So I think having default initialization by default but allowing the programmer to opt out is probably the right way to handle this.

Currently, D allows you to @disable this() for user-defined types, but it doesn't give you any way to opt out of T.init. This is something that should be improved. If disabling T.init entirely is too disruptive, there should at least be a way to make T.init accessible only in @system code.

October 24, 2023

On Monday, 23 October 2023 at 22:45:29 UTC, Paul Backus wrote:

>

On Monday, 23 October 2023 at 18:54:45 UTC, IGotD- wrote:

>

What is your take on this and if D would ever be modernized, is this something that D should consider?

Most of the time, default initialization is what you want, and it doesn't cause any problems. So I think having default initialization by default but allowing the programmer to opt out is probably the right way to handle this.

Currently, D allows you to @disable this() for user-defined types, but it doesn't give you any way to opt out of T.init. This is something that should be improved. If disabling T.init entirely is too disruptive, there should at least be a way to make T.init accessible only in @system code.

@disable this plain doesn't work. It prevent things in some cases, but utltimately fails to enforce the invariant it sets out to enforce.

October 24, 2023

On Monday, 23 October 2023 at 22:45:29 UTC, Paul Backus wrote:

>

Currently, D allows you to @disable this() for user-defined types, but it doesn't give you any way to opt out of T.init. This is something that should be improved.

Right!

October 24, 2023

On Monday, 23 October 2023 at 18:54:45 UTC, IGotD- wrote:

>

What is your take on this and if D would ever be modernized, is this something that D should consider?

Sorry don't have any issue with T.init.
It's not like because it's in D and have not changed for 5 years that it must be bad.

« First   ‹ Prev
1 2