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.
This Week in D is in the process of being hosted at dlang.org. Starting soon, you'll be able to find this publication there.
The London D Programmers MeetUp will be on Tuesday, February 3rd at Skills Matter.
A 2015 H1 Vision was released by Walter and Andrei, laying out a longer term vision. The announcement thread has some discussion, and another concern was raised about incorporating bare metal programming needs into the vision.
A relatively minor change was implemented, but possibly will be removed before the official release out of concern of making D too unstable or too full with a large quality of minor features. The debate is ongoing at this moment.
Early bird registration is open! For $250 in February only, you can register to attend DConf 2015 which will be held May 27-29 at Utah Valley University in Orem, Utah, in the United States.
The talk submission deadline is this month! If you have something to say about D at the conference, please submit soon!
Hope to see you there!
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 learn a bit about destructors. Destructors in D are sometimes run by the garbage collector, especially when present in classes (as opposed to structs), which means some care should be used with them. Namely, pretend the GC is a null pointer, so don't use any GC allocated child objects and do not attempt to allocate any new GC memory.
If a destructor is called by the garbage collector, it happens as the object is being collected. Since D uses a mark and sweep collector, child objects are marked as dead at the same time as their parent, and may be swept up first. As a result, member variables that are references to garbage collected memory may be invalid.
class Foo { string b; ~this() { // invalid reference to b // since it is a child object // that refers to GC memory, // b may already be freed by the // time this destructor is called writeln(b); } }
Moreover, trying to allocate garbage collected memory during a collection cycle will trigger the invalid memory operation error at runtime, killing the program.
class Foo { ~this() { // invalid memory operation error: // to!string allocates a new string, // which cannot be done during a // collection cycle. writeln(to!string(10)); } }
Class destructors have limited use and should be used with care. Decorating them with @nogc will help you avoid allocations, but you are on your own about avoiding GC referenced memory.
Best practice is to only use value type members in destructors. A practical, common example would be pointers to C memory or objects. For example, you may call free() on a pointer returned by malloc().
Destructors on stack allocated objects, typically structs, are a different story. Since they are run automatically (and deterministically) upon the object going out of scope instead of by the garbage collector, these restrictions do not apply.
Bottom line, if you want to use destructors, put them in structs and declare them normally, without using pointers or new. They will then work like in C++.
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.
This week, I'm going to start spotlighting the components I've written that can be used for simple game development.
The first module in the spotlight is simpledisplay.d, which provides facilities to create a window in a cross-platform (Windows and X11 are actively maintained) manner. The window can be drawn inside with 2d primitives or OpenGL and will feed events to your program. You can create several windows as well, integrate with a generic event loop on Windows, and get access to the native handles for further use.
simpledisplay.d has no dependencies outside of my own color.d, which itself doesn't even depend on Phobos. This means it can compile very quickly and make small executables - about 180 KB on Windows for a GUI program, statically linked with no DLL requirements.
To get started, download color.d and simpledisplay.d from my github.
Then, in the same directory as those two files, create a file window.d with these contents:
import simpledisplay; void main() { enum width = 300; enum height = 300; auto window = new SimpleWindow(width, height); window.eventLoop(0); }
Compile with: dmd window.d color.d simpledisplay.d and run the program. You'll see a window pop up and you can close it with the normal GUI interface.
Next, we'll add drawing and event handling:
import simpledisplay; void main() { enum width = 300; enum height = 300; auto window = new SimpleWindow(width, height); window.eventLoop(0, (MouseEvent ev) { if(ev.type == MouseEventType.motion) { auto painter = window.draw(); painter.clear(); painter.fillColor = Color.red; painter.drawRectangle(Point(ev.x - 7, ev.y - 7), 15, 15); } } ); }
Compile and run the program, then move the mouse around in the window. A red square will be drawn under the mouse as you move it.
Drawing in simpledisplay.d is done in one of three ways:
The object returned by window.draw is a struct that automatically double buffers drawing routines. When the painter goes out of scope, its destructor will swap the active and drawing buffers, making your contents visible. When you draw, always make sure it is in a limited lifetime scope to see the results.
void main() { int a; { Struct s; // a is still in scope and this // code is run in sequence - the {} // just introduces a lexical scope, // it doesn't define a new function. } // s.dtor is called now // s is no longer in scope }This should not be confused with a delegate literal:
void main() { auto a = { Struct s; }; // a is a delegate now - the code inside those // braces is NOT automatically run a(); // but it is run now }The difference braces at the top level when the parser is looking for a statement introduces a new scope, whereas braces when the parser is looking for an expression introduces a delegate literal.
The eventLoop function takes one or more arguments. The first argument is an integer which sets a timer pulse for that number of milliseconds. If passed 0, it never pulses on a timer, so it will wait forever for another GUI event. If passed some other value, it will call an event handler with zero arguments as much as it can, up to that point. This gives the foundation for animations and games.
Each argument after the timeout are event handlers. Inspired by std.concurrency, it matches events to handlers by the type of arguments the handler receives.
window.eventLoop(500, // without the delegate keyword, this would be a function // and fail to compile. delegate () { writeln("pulse triggered."); });The difference between a delegate and function is that a delegate has a context pointer. If a code literal doesn't need to access any enclosed variables, it will be automatically typed function. Specifying either function or delegate will force it to be one or the other.
Here, we add a handler for MouseEvent and react to it by drawing. Other events we can watch for are () - no arguments for timer pulse, KeyEvent for key press and release events, or dchar for higher-level a-character-was-typed events. It is also possible to handle window resize events and low-level native OS events with other functions. simpledisplay.d tries to get out of your way when you don't want it, so it helps to bootstrap a simple program without limiting you when you need more advanced capabilities.
This is just the beginning of what simpledisplay.d can do. It also has functions for accessing the clipboard and other GUI features. minigui.d uses native Windows widgets or custom Xlib code on top of simpledisplay.d to start building multi-window GUIs. On Linux, it can integrate with eventloop.d to merge events from several asynchronous sources. It also gives a foundation for writing 3D graphics and platform-specific applications like X Window managers.
In the next installments in this series, we'll look at using OpenGL with simpledisplay.d, then we'll look at its sister modules, simpleaudio.d and joystick.d, to start building a simple game in D with minimum outside dependencies.
To learn more about D and what's happening in D: