A Beginner's Guide to D/D Transition Guide

From Wikibooks, open books for an open world
Jump to: navigation, search

Introduction[edit]

This is meant to be a very fast-paced tutorial to D for experienced programmers. Instead of spending a long time explaining D, this text will demonstrate various D features and let them speak for themselves. If you are debating whether D is the language for you, you have two general approaches:

  • Read a bunch of languages comparisons, articles, and flamewars about D.
  • See how it works.

If you'd like to take the former, Google is your friend. You might also want to start off at Digital Mars's D Homepage.

If the latter is your cup of tea, you're in the right place. We'll start off small and progressively show more advanced features until we've covered all the major points of the language. Additionally, if you'd like more examples of any specific topic, the DSource Tutorials Project is the right place for you.

What We'll Cover[edit]

For now, we will only cover core language features and the bare minimum library calls required to utilize them. One of the first things you should realize about D, as opposed to C++ and Java, is that it includes in the language many features relegated to libraries in its predecessors. So while a Java tutorial would be remiss in not mentioning java.util.ArrayList, in D we get by with int[]. (More on this later.)

Style of This Guide[edit]

Each section will have a code snippet and a description of how D differs from its predecessors. Usually, that will be sufficient; occasionally, there will also be an explanation of a feature which is vastly different (read: revolutionary versus evolutionary).

The Guide[edit]

Hello World[edit]

import std.stdio;
 
void main() {
        writeln("Hello World!");
}
  • As you can see, D is more Java-like in that it uses import statements instead of #include. In fact, D has no preprocessor at all. Don't worry; you'll see how to do almost all your preprocessor tricks with D itself.
  • main can return void.
  • std.stdio and writefln are part of the library, so we won't really discuss them here. Sufficed to say, writef follows the printf family of functions and writefln adds the Java-like "ln" suffix to denote newline.

Arrays (and more)[edit]

import std.stdio;
 
void main() {
        int[] ages; //1
        ages = [15, 23, 14, 29]; //2
        int sum; //3
        double average = void; //4
 
        writefln("%d %f", sum, average); //5
        writefln("We have %d ages", ages.length); //6
 
        for(int i = 0; i < ages.length; ++i) //7
                sum += ages[i];
 
        average = (cast(double)sum) / ages.length; //8
 
        writefln("Average age: %.2f", average);
}
  1. We use int[], as opposed to int ages[] or int* ages or int *ages. Arrays are proper types in D, not just aliases for pointers. Those familiar with scripting languages like Perl and Python should find this much more comfortable. For the rest of you, wait a few minutes and then you'll appreciate it.
  2. Array literal.
  3. Notice that I didn't set it to 0. Shouldn't I be worried about some arbitrary data? Nah, D sets all variables to a default value.
  4. Well, unless I specify otherwise by setting it to void.
  5. We use writefln to print formatted lines, much like printf in C. It prints 0 and then some arbitrary junk.
  6. What is this? Arrays have properties attached to them, like length. It can be very convenient, especially when dealing with dynamic arrays (later).
  7. The for loop is totally unchanged. But we really shouldn't use a for loop here. You'll learn about foreach later on.
  8. Casts are all explicitly specified with the cast keyword.

Strings[edit]

import std.stdio;
 
void main() {
        string firstname, lastname, fullname; //1
        firstname = "Walter"; //2
        lastname = "Bright";
        fullname = firstname ~ " " ~ lastname; //3
        writefln("Congratulations on making a great language " ~ fullname); //4
 
        char[] a = firstname.dup;//5
        char[] b = a;
        a[0] = 'H'; //6
        writefln(b); //prints "Halter"
        firstname = "Jacob";//7
        writefln("Your name is still %s, right?", fullname); //8, prints Walter Bright
}
  1. Strings are character arrays which cannot be modified on a per element basis. You'll see more about arrays later. Another major note is that D strings are not null terminated. Arrays simply keep track of their length.
  2. firstname is assigned to "Walter".
  3. ~ is the concatenation operator. There is no ambiguity between + and ~ for strings.
  4. One way of outputting, although number 8 is better
  5. To modify a string, we get a duplicate (a copy) of the string. .dup returns a mutable copy of an array.
  6. Since b is really a pointer to a, b actually gets modified on this line. firstname remains unchanged.
  7. Although we cannot change string on an per element basis, we can re-assign them.
  8. Since fullname was created through concatenation, it also remains unchanged.

Dynamic Arrays and Foreach[edit]

import std.stdio;
 
// this is a rather contrived example, please forgive me
void main() {
 	int[] squares; //1
 
 	for(int i = 0; i*i < 273; ++i) { // just some random range
 		squares.length = i+1; //2
 		squares[i] = i*i;
 	}
 
 	foreach(ref square; squares) //3, 4
 		square %= 10; // again, something arbitrary
 
 	squares.sort; //5
 	writefln("Total of %d squares", squares.length);
 	foreach(index, square; squares) //6
 		writefln("%d: %d", index+1, square);
}
  1. Defining a dynamic array is very intuitive; simply omit the length.
  2. Extending a dynamic array is simply done by resizing it.
  3. foreach is awesome. Here's the simple case: the part before the semicolon is the variable from the array, and the one afterwards is the array. And yes, foreach can work with much more than just arrays.
  4. ref simply means pass by reference. Without this, the original array would be unaffected.
  5. Built-in sort. If I'm not mistaken, both implementations use a quicksort, which- as its name implies- is pretty good.
  6. And now another form of foreach. The left-side of the semicolon can specify two variables, separated by a comma. In this case, the first is the index (think of "i" in your typical for loop) and the second is the value.

If you feel like there's something missing in the above code, you're right: I didn't put the data type on the variables in the foreach loop. D actually supplies an "auto" keyword which means "automatically figure out what type I want," and it is implicitly understood in the foreach loop if a type is missing.

I know I lumped many important things together in this example. The rest of the guide should elucidate all these topics to a greater extent, but you can always read up the official language specs or look at the dsource tutorials if you like.

Associative Arrays[edit]

import std.stdio;
 
void main(char[][] args) { //1
	int[char] charCount; //2
	foreach(arg; args[1..$]) //3
		foreach(c; arg)
			++charCount[c]; //4
	foreach(c; charCount.keys.sort) //5
		writeln(charCount[c], " copies of character '", c, "'"); //6
}
  1. In order to pass in arguments, we simple have main receive an array of strings. Unlike C/C++, we needn't worry about "int argc" since arrays know their own length.
  2. To define an associative array, you simple put a value type inside the square brackets; otherwise it's like a normal array. You can put any type in there (classes, arrays, etc.). However, if you use objects as keys, keep in mind that you'll have to do some fancy stuff with hash functions and opCmp (which is beyond the scope of this document, but described fully in D Programming Language- Arrays.
  3. This "1..$" construct is a slice of an array; it means "return an array which includes the element at index 1 all the way to the end ($)". There are other ways of doing this, such as "1..length", but this one can be very nifty. If you're wondering why we would ignore the first element, it's because, like in C/C++, the first element is the name of the program.
  4. In order to access elements of an associative array, you simply give an index of the key type for it.
  5. All associative arrays have a property called "keys" (along with others like values and length) which returns an array of all the keys. Like any other array, you can then call the property sort on that.
  6. This is just an alternative way to print lines, each argument is simply converted and printed sequentially.