Welcome to This Week in D! Each week, we'll summarize what's been going on in the D community and write brief advice columns to help you get the most out of the D Programming Language.
The D Programming Language is a general purpose programming language that offers modern convenience, modeling power, and native efficiency with a familiar C-style syntax.
This Week in D has an RSS feed.
This Week in D is edited by Adam D. Ruppe. Contact me with any questions, comments, or contributions.
A blog post was written about using exceptions in @nogc functions, suggesting various options.
See more at digitalmars.D.announce.
See more at forum.dlang.org and keep up with community blogs at Planet D.
This week, we'll talk about skipping initialization of variables.
D automatically initializes all variables to a static value, their .init property. This is typically zero, but ideally is some invalid data to make usage of an uninitialized variable obvious at runtime. For pointers, it initializes them to null. Floating points are set to a signaling NaN value. Chars are set to 0xff, an invalid Unicode character.
Sometimes, though, you don't want a variable auto-initialized and D provides a way to do it: by explicitly writing = void in the initializer:
T t = void; // t will not be auto-initialized
When do you want this? Very rarely, but there are three general areas:
1: When you are forced to by a @disabled default constructor on a struct. When a struct has @disable this(); in it, default construction is disabled. This means that all declarations of variables of this type must be explicitly initialized - or explicitly uninitialized.
struct YourStruct { this(int some_arg) {} @disable this(); } void main() { YourStruct s; // Error: variable b.main.s default construction is disabled for type YourStruct YourStruct s = YourStruct(some_arg); // OK YourStruct s = void; // also OK! }
It is very important to still set up your struct appropriately, so it passes its object invariants, so typically this is only done in internal functions that know the struct's innards well enough to do it right
2: When you know the default initialization is a complete waste of time and you want to optimize it away manually
.int[1000] a = void; // initialized below // a is normally set to all zero, but here it is // left as garbage because we initialize it right // below foreach(idx, ref item; a) item = idx; // now it is initialized anyway
This is dangerous if the code is refactored and the initialization gets lost, so only do it if you know it will actually make a relevant difference in your case. Moreover, you probably ought to comment why it is set to void at the declaration point so future reading of your code in the future will understand your intention.
3: Initialization depends on runtime logic, but you want to scope the variable outside those conditionals. For example:
Struct s = void; if(somecond) { s = option1; } else { s = option2; }
In this example, you could also initialize it with a ternary operator (Struct s = somecond ? option1 : option2;) or a helper function that encapsulates the condition, but this also provides a way. This reasoning, especially coupled with one or both of the other scenarios (e.g. default construction is disabled, but the value depends on the runtime condition) is a common reason to see void initialization in the wild.
Find more D tips at the D idioms list or buy my D Cookbook for a more in-depth examination of many D tricks.
If you'd like to submit a tip, email me.
To learn more about D and what's happening in D: