Examples¶
D is a complex multi-paradigm programming language. At the same time, if you know C programming language and you want to start using D then you just need to look through some examples.
Tip
All examples available on GitHub.
Hello, World!¶
C programs can be easily translated to D. The following program prints “Hello, World!” to the standard output.
#include <stdio.h>
const char* const nullTerminatedStrPtr = "Hello, World!";
int main(void)
{
puts(nullTerminatedStrPtr);
return 0;
}
D doesn’t have a preprocessor.
Use import core.stdc.MODULE;
construction to import MODULE
from the C Standard library.
import core.stdc.stdio;
// terminates with a null character
immutable char[] nullTerminatedStr = "Hello, World!\0";
int main()
{
// calls external C function
puts(nullTerminatedStr.ptr);
return 0;
}
Module core.stdc.stdio
contains the puts
prototype:
extern(C) @system nothrow @nogc int puts(in char* s);
Common D “Hello, World!” program which is based on Phobos looks more simple:
/++
Deduces the type of a declared variable from its initialization
expression.
+/
immutable str = "Hello, World!";
void main()
{
// Scoped and selective imports can be used.
import std.stdio : writeln;
writeln(str);
}
Phobos is the standard runtime library that comes with the D language compiler.
See also
To find a collection of common C techniques, and to find out how to do the corresponding task in D click here. However most of them can be implemented in C style.
Simple project with dub¶
DUB is a build tool for D projects with support for automatically retrieving dependencies and integrating them in the build process. The design emphasis is on maximum simplicity for simple projects, while providing the opportunity to customize things when needed.
To create the initial project with name component
, run dub init component
.
Remove automatically created component/source/app.d
file
and create the following file structure
dub.json
component/
source/
component/
mod.d
package.d
where component/package.d
is the main module component
/++
Pacakge component
+/
module component;
public import component.mod : removeSingleLineComments;
and component/mod.d
is the inner module component.mod
/++
Module mod;
+/
module component.mod;
import std.algorithm, std.ascii, std.range, std.string, std.functional;
/++
Reads forward range `ir` and removes single line comments.
The result is stored in output range `or`.
Params:
or = output range
ir = input range
cmt = comment prefix (like // in C or # in Python)
+/
void removeSingleLineComments
(OutputRange, Range1, Range2) // template parameters
(OutputRange or, Range1 ir, Range2 cmt) // function parameters
{
foreach(line; lineSplitter(ir))
{
if(line.save.find!(not!isWhite).startsWith(cmt))
continue; //skips line
put(or, line.until(cmt)); //skips comment
put(or, "\n");
}
}
/// Unittests with comment appears in documentation.
unittest
{
auto app = appender!string;
// A string that contains a code with C-like block syntax
// can be framed with `q{` and `}`.
immutable textBefore = q{
// main function
int main()
{
// return statement
return 0; //returns 0
}
};
immutable textAfter = q{
int main()
{
return 0;
}
}; // Note: "return 0; " ends with a space character.
removeSingleLineComments(app, textBefore, "//");
debug
{
import std.stdio;
writeln("text:", app.data);
}
assert(app.data == textAfter);
}
To test this module, run dub test
from package’s folder.
removeSingleLineComments
can be imported with import component;
or import component.mod;
.
To use component package, put the following dependency into your project’s dub.json into the dependencies section:
{
...
"dependencies": {
"component": "~master"
}
}
Plotting with matplotlib (python)¶
These are two projects that can be used with the D programming language:
But these two are not so convenient to use, in comparison with matplotlib.
matplotlib is a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms. matplotlib can be used in python scripts, the python and ipython shell, web application servers, and different graphical user interface toolkits. To integrate with python the PyD package can be used.
PyD is a library that provides seamless interoperability between the D programming language and Python. The minimal configuration file for this example is
{
"name": "plotting_example",
"dependencies": {
"pyd": "~>0.9.4",
},
"subConfigurations": {
"pyd": "python34",
},
}
Note
The python and matplotlib should be installed. PyD searches the version of the python that is noted in the sub-configuration ("pyd": "python34"
in this example). For more information, see the PyD’s dub configuration file.
The following program
reads data from a file and runs show_histogram.py
.
import pyd.pyd;
import pyd.embedded;
import pyd.extra;
/++
`srcipt` is a string that contains the python code to execute.
Alternatively, you can put your python code here:
--------
immutable script = `
YOUR = "PYTHON"; CODE = "HERE"
print(YOUR, CODE)
`;
--------
where string is framed with backtick character.
+/
immutable script = import("show_histogram.py");
/++
`d_to_python_numpy_ndarray` converts a D array to numpy.ndarray.
`toNumpyArray` is only an alias.
+/
alias toNumpyArray = d_to_python_numpy_ndarray;
/++
A static constructor is a function that performs initializations of
thread local data before the `main()` function gets control for the
main thread.
Shared static constructors are executed before any static
constructors, and are intended for initializing any shared global
data.
+/
shared static this() {
//initializes PyD package.
py_init();
}
void main()
{
auto pythonContext = new InterpContext();
/+
Uniform Function Call Syntax (UFCS)
is used in the following line of code.
Equivalent code would be just:
--------
pythonContext.sample = toNumpyArray(readData("data/data.txt"));
--------
+/
pythonContext.sample = "data/data.txt".readData.toNumpyArray;
pythonContext.num_bins = 50;
pythonContext.py_stmts(script);
}
double[] readData(string file)
{
import std.algorithm.iteration : map, splitter;
import std.array : array;
import std.conv : to;
import std.file : readText;
return file
.readText //Reads the contents of a text file into a string.
.splitter //Lazily splits words.
.map!(to!double) //Lazily converts words to doubles.
.array; //Creates an array.
}
show_histogram.py
is located in views/
folder that is used by dub as a default string import [1] folder.
# variables `sample` and `num_bins` should be defined in context
import matplotlib.pyplot as plt
n, bins, patches = plt.hist(sample, num_bins, normed=1)
plt.show()
[1] | Strings can be imported at compile time. |
Web Application¶
Web application is a pretty good example of the last chapters of any book, where the reader is suggested to make use of the means of expression in the language. As a rule, web application is a complex product, both in terms of knowledge of the language and in terms of code complexity of the used libraries.
And this example is no exception. Then why do people who want to learn D language very quickly still need example of web app? Many of them have a reason and it is that they need to integrate quickly programs written in D with other services, programming languages and databases.
The article “Creating a simple restful web app with node.js, Express, and MongoDB” by Christopher Buecheler is taken as a basis for this example.
Initialization¶
To create a skeleton web application, run:
$ dub init vibed-mongo vibe.d
This will make the directory vibed-mongo
with a minimal HTTP server based on vibe.d.
The configuration file dub.json
will look something like this:
{
"name": "vibed-mongo",
"dependencies": {
"vibe-d": "~>0.7.23"
},
"versions": ["VibeDefaultMain"],
"authors": ["Christopher Buecheler", "Ilya Yaroshenko"]
}
The version "VibeDefaultMain"
includes the main function defined by default.
The project has the following structure:
dub.json - package information
source/ - D source code
app.d
service.d
views/ - Diet templates
index.dt
layout.dt
public/ - static directories
javascripts/
global.js
styles
style.css
favicon.ico
After installing MongoDB, run the server
$ mongod
In another console run the Mongo interpreter
$ mongo
> use vibed
switched to db vibed
> db.createCollection("userlist", {autoIndexID : true})
{ "ok" : 1 }
> db.userlist.insert({
'username' : 'test1',
'email' : 'test1@test.com',
'fullname' : 'Bob Smith',
'age' : 27,
'location' : 'San Francisco',
'gender' : 'male'
})
WriteResult({ "nInserted" : 1 })
> exit
bye
The above script creates a vibed
database with a userlist
collection, which will contain one record.
Patches¶
Comparing with the original article global.js
was slightly changed:
$.ajax({
type: 'POST',
data: newUser,
url: '/users/adduser',
success: function(data){
$('#addUser fieldset input').val('');
populateTable();
},
error: function(xhr, textStatus, error){
alert(xhr.responseText);
}
});
$.ajax({
type: 'DELETE',
url: '/users/deleteuser/' + $(this).attr('rel'),
success: function(data){
populateTable();
},
error: function(xhr, textStatus, error){
alert(xhr.responseText);
}
});
Diet Templates¶
Diet templates are HTML templates which are statically compiled down to native D code. Diet templates syntax equals that of Jade templates with the exception of some of the advanced syntax features.
First lines of index.dt
:
extends layout
block content
- /++
- The main difference is that you write D expressions and
- statements instead of JavaScript.
- +/
- import std.format;
- auto fullTitle = format("%s web app", title);
h1= fullTitle
p Welcome to our test
Service¶
vibe.d
is a good example of the use of declarative programming with D.
Service performs an insert, select and remove operations for user entries at a mongo collection.
module service;
import std.conv;
import vibe.d;
class MongoService
{
private MongoCollection collection;
const string title;
this(MongoCollection collection, string title = "")
{
this.collection = collection;
this.title = title;
}
void index()
{
logInfo("MongoService: GET /");
render!("index.dt", title);
}
void postAdduser(
string username,
string email,
string fullname,
uint age,
string location,
string gender,
HTTPServerResponse res,
)
{
import vibe.utils.validation;
logInfo(text("MongoService: POST /adduser : ", username));
enforce(age < 200, "wrong age");
auto bson = Bson.emptyObject;
bson.username = validateUserName(username);
bson.email = validateEmail(email);
bson.fullname = fullname;
bson.age = age;
bson.location = location;
bson.gender = gender.toLower;
collection.insert(bson);
res.writeBody("");
}
Json getUserlist()
{
logInfo("MongoService: GET /userlist");
return Json(collection.find!Json.array);
}
@path("deleteuser/:id")
@method(HTTPMethod.DELETE)
void pullOutUser(BsonObjectID _id, HTTPServerResponse res)
{
logInfo(text("MongoService: GET /deleteuser/", _id));
collection.remove(["_id": _id]);
res.writeBody("");
}
}
App¶
The following static constructor connects vibed
database, creates the HTTP server and implements the error handler.
import vibe.d;
import service;
shared static this()
{
immutable string title = "vibe.d";
logInfo("Connecting to DB...");
auto db = connectMongoDB("localhost").getDatabase("vibed");
auto collection = db["userlist"];
logInfo("Creating service...");
auto mongoService = new MongoService(collection, title);
auto mongoServiceSettings = new WebInterfaceSettings;
mongoServiceSettings.urlPrefix = "/users";
logInfo("Setup router...");
auto router = new URLRouter;
router.registerWebInterface(mongoService, mongoServiceSettings);
router
.get("/", (req, res)
{ res.redirect("/users"); } )
.get("*", serveStaticFiles("public/"));
logInfo("Setup HTTP server...");
auto settings = new HTTPServerSettings;
with(settings)
{
bindAddresses = ["127.0.0.1"];
port = 8080;
errorPageHandler =
(req, res, error)
{
with(error) res.writeBody(
format("Code: %s\n Message: %s\n Exception: %s",
code,
message,
exception ? exception.msg : ""));
};
}
//Listening http://127.0.0.1:8080
listenHTTP(settings, router);
}