Your first D program
What D is for, what the compiler needs before anything runs, and the smallest complete program: one main function, one import, and a few lines of output.
What D is for
D is a compiled language from 2001 that aims at two things at once: the speed and control of C, and the conveniences of a modern language. Modules, garbage collection, slices and templates are part of the language itself rather than add-ons, and a program is compiled ahead of time into a native binary by a compiler such as dmd or ldc.
The payoff is that a short program stays short. There is no header file to write, no separate declaration to keep in step with a definition, and no build file for a single source — one file called main.d is enough to begin, which is exactly what this page runs.
The shape of every program
A D program starts at void main(). The word void says the function hands nothing back to the system, main is the name the runtime looks for, and the braces hold the body. Each statement inside ends with a semicolon, so the line break is for the reader rather than for the compiler.
import std.stdio; on the first line brings in the standard input and output module. Without it the compiler does not recognise the name writeln and stops with an error, which is the first error most people meet: a program that is correct apart from a missing import.
Printing with writeln
writeln takes any number of arguments, turns each one into text, writes them one after another with no separator, and adds a newline at the end. write is the same call without that newline. There is no << and no placeholder syntax to learn, because the values themselves know how to describe themselves.
Values are printed in the order you list them, and the separator is whatever you put between them. In the example the character ! follows the greeting directly, the number follows a literal space, and each writeln finishes its own line.
The newline is the difference between a report and a wall of text. write leaves the cursor where it stopped, so a second call continues the same line — useful for building a line in pieces, confusing when you expected two. writeln() with no arguments prints just the newline, which is how a blank line is written.
From text to a running binary
Pressing Run does not interpret the file line by line. The text goes to dmd, which reads it in stages: the lexer turns characters into tokens, the parser checks that those tokens form statements, and the semantic pass resolves every name against the modules that were imported. Only then does code generation produce machine instructions, and a linker joins them with the runtime that provides writeln and the garbage collector.
Each stage can refuse the program, which is why one mistake can produce several messages. Fix the first error, run again, and let the rest disappear with it.
The runtime is linked in whether or not you call it. Even a program that prints nothing carries the garbage collector and the startup code that calls main, which is why the binary is larger than the source and why the first build takes longer than the ones after it.
main is a contract
The runtime calls main after it has set up the standard streams and the garbage collector. void main() is the shortest form and reports success when it finishes. int main() may return a status instead, where zero means the program did what it was asked and any other number marks a failure the shell can read.
The compiler accepts either form, but it will not accept a function called Main or a file with no main at all. It can also take the command line as string[] args; this course keeps to the empty form because every lesson runs with no arguments.
The smallest complete program
import std.stdio;
void main() {
writeln("one line");
writeln("another line");
}Run it, then make it yours
Press Run to see the program compile and print. Then change the language name and the year, add a third value to the line that prints two numbers, and run again.
Change a value and press Run again. The run goes to a real D compiler on the server, so the first one may take a few seconds and every one returns the diagnostics you would see on your own machine.
One line from several writes
Press Run and notice that the first four calls produce a single line. Then add a `write` of your own before the full stop, and a second line that mixes text with a calculation.
Three mistakes account for most first runs: a missing semicolon at the end of a statement, a string opened with a single quote, which makes a char and fails as soon as it holds more than one character, and a call to writeln without import std.stdio;. Read the first message the compiler prints; the ones after it are usually consequences.
Try these next
- Add a fourth
writelnthat prints a sum, a word and aboolin one call, and predict the line before you run it. - Change
void main()toint main(), addreturn 0;at the end, and confirm the output is unchanged. - Delete the import, read the compiler message, then put it back and confirm the program runs again.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
Where does a D program begin?
