D Feature Examples

Flattr this

This heading intentionally left blank

In my opinion, D is a great programming language. You can do things any way you want, you do not have to care about the techniques used behind the stage.

While D is very flexible and high-level, it is very fast. Programming languages like Java use strange things like bytecode. If you are not sure that Java is bad, then just look at the typical run-time behavior of Java programs. And there are still a lot of points why you should not use Java (type system, security, ugliness, etc.).

But we are not here to talk about Java or stuff like C#. We are here to learn a few key features of the D programming language.

If you want to follow this introduction, you must have knowledge in programming languages like C or PHP.

Compiler

Walter Bright, one of the world's greatest compiler developers and programmers, invented D. And he also invented the most successful D compiler, Digital Mars D. You have to choose the right package for your platform. DMD supports all language features of D. Partial DMD is Free Software, partial only Open Source.

There exist other compilers for D. But this tiny introduction uses the original D compiler, DMD.

nothing.d

import std.stdio;

void main(string[] args) {
	// code here
}

Compile command: dmd nothing.d
Run command: ./nothing (GNU/Linux) or nothing.exe (Win32)

This program does nothing. import std.stdio means to embed the standard input/output features in the program.

Every D program has to contain a main() function. It consists of the return type void (that means: nothing is given back to the calling function) and the function arguments (string[] args). Your Operating System (GNU/Linux, Windows, etc.) will call the main() function and has the responsibility to deliver the function arguments. What these function arguments contain will be described in the next paragraph.

args.d

import std.stdio;

void main(string[] args) {
	foreach (key, value; args) {
		writeln(key,"\t",value);
	}
}

Call: ./args abc foo bar 42 "D Programming" and try to understand what args is.

foreach() is a special loop. It is used to iterate over D arrays. foreach() is really unique for compiled programming languages. For example, it is rather difficult in C++ to iterate over an associative array. This can be easily done in D with foreach(). Associative arrays (also called hash maps) are one of the key features of D.

hashmap.d

import std.stdio;

void main(string[] args) {
	int[string] age;
	
	age["John"] = 42;
	age["Mary"] = 24;
	age["Tiny Tim"] = 11;
	
	foreach (key, value; age) {
		writeln(key," is ",value," years old.");
	}
}

I wrote a little C++0x program that does the same things like our D program.

#include <string>
#include <unordered_map>
#include <iostream>

using namespace std;

int main(int argc, char** argv) {
	unordered_map<string, int> age;
	
	age["John"] = 42;
	age["Mary"] = 24;
	age["Tiny Tim"] = 11;
	
	for (unordered_map<string, int>::const_iterator iter
		= age.begin(); iter != age.end(); ++iter) {
		cout << iter->first << " is " <<
			iter->second << " years old.\n";
	}
	
	return 0;
}

As you can see, our D example is more or less self-explanatory while the C++ example is not. In C++, it is difficult to iterate over an associative array (map). This can only be done with creepy for-iterator loops.
But in D, you can use foreach for things like that.

I think you are old enough to decide for yourself which way is better.

vectors.d

import std.stdio;

void main(string[] args) {
	int[] table = [0,1,2,3,4,5,6,7,8,9,10];
	int i = 0;
	
	table[] *= table[];
	
	foreach (value; table) {
		writeln(i,"^2 = ",value);
		i++;
	}
}

First of all, a dynamic array table is initialized. For now, it contains the ints 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10. You can add new elements everywhere in the source code.

The interesting line is table[] *= table[];. That means that every single element in the table[] dynamic array is multiplied by itself. In other programming languages, you would need at least one extra loop, but D is able to do things like that directly.
Try to understand the rest of the source code.

templates.d

import std.stdio, std.bigint;

T max(T)(T a, T b) {
	if (a > b) return a;
	else return b;
}

void main(string[] args) {
	writeln("max(3,6) = ",max(3,6));
	writeln("max(3.4,3.45) = ",max(3.4,3.45));
	writeln("max(1266712676636267235651,1266712676636267235652) = ",
	 max(BigInt("1266712676636267235651"),BigInt("1266712676636267235652")));
}

Templates are a very powerful feature of C++, that have found their way into D. For example, you do not have to write one function that compares two floats and one function that compares two ints. For example, it is possible to write only one function max with the pseudo-type T and your function will return the numeric bigger variable, no matter which type it is of. This example works only with numeric values; max("Abc","foo") should not work reliable. (Surprisingly, it does.)

strings.d

import std.stdio, std.conv;

void main(string[] args) {
	string a = "The quick brown fox";
	
	a ~= " jumps over ";
	
	a ~= to!string(42);
	
	a ~= " lazy dogs.";
	
	a ~= "\n args[0] == ";
	
	a ~= args[0];
	
	writeln(a);
}

Here we have a string called a. D strings are a very interesting feature because they are self-allocating. Everytime you add new content to the string, D automatically allocates the right number of bytes. DMD also determines whether Heap or Stack allocation has to be used. Of course, your string will be garbage collected at the end of your program.

Importing std.conv can be very useful. You can do lots of cool conversions with this library. Look at what we did when we wrote to!string(42). That's great, isn't it?

sorting.d

import std.stdio;

void main(string[] args) {
	int[] tbs = [87, 2, 84, 55, 11, 91, 3, 5, 6, 9, 12, 2291];
	
	tbs.sort;
	
	foreach (value; tbs) {
		writeln(value);
	}
}

Sorting could not be easier. Try to understand this example.