D Language
D Language
#d
Table of Contents
About 1
Remarks 2
Versions 2
Examples 2
Installation or Setup 2
Package Managers 2
Arch Linux 2
Chocolatey 2
Gentoo 2
OSX Homebrew 2
Debian/Ubuntu 3
Other compilers 3
IDEs 3
Hello World 3
Hello, World! 3
Explanation : 4
Examples 6
Standard use 6
Literals 6
Chapter 3: Classes 8
Syntax 8
Remarks 8
Examples 8
Inheritance 8
Instantiation 8
Remarks 10
Examples 10
Chapter 5: Contracts 11
Remarks 11
Examples 11
Function contracts 11
Function contracts 11
Syntax 12
Remarks 12
Examples 12
Array operations 12
Slices 12
Syntax 14
Remarks 14
Examples 14
Global imports 14
Selective imports 15
Local imports 15
Public imports 15
Renamed imports 15
Module declaration 16
Chapter 8: Loops 17
Syntax 17
Remarks 17
Examples 17
For loop 17
While loop 17
do-while 18
Foreach 18
Syntax 20
Examples 20
Pointers 20
@safe D 20
Remarks 22
Examples 22
Syntax 24
Remarks 24
Examples 24
Remarks 26
Examples 26
Reversing a string 26
Empty string 26
Null string 26
Test for empty or null 27
References 27
String to ubyte[] 28
ubyte[] to string 28
References 28
Examples 29
Struct Constructors 29
Syntax 30
Examples 30
template 30
Syntax 32
Examples 32
Syntax 34
Remarks 34
Examples 34
Syntax 36
Examples 36
Unittest blocks 36
Executing unittest 36
Annotated unittest 37
Credits 38
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: d-language
It is an unofficial and free D Language ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official D Language.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
Chapter 1: Getting started with D Language
Remarks
D is a systems programming language with C-like syntax and static typing. It combines efficiency,
control and modeling power with safety and programmer productivity.
Versions
D http://www.digitalmars.com/d/1.0/changelog.html 2007-01-23
D2 https://dlang.org/changelog/2.000.html 2007-06-17
Examples
Installation or Setup
The D programming language's standard compiler DMD can run on all major platforms. To install
DMD see here. To install by command line you may run the command (found on the D website):
Package Managers
Arch Linux
pacman -S dlang
Chocolatey
Gentoo
layman -f -a dlang
OSX Homebrew
https://riptutorial.com/ 2
brew install dmd
Debian/Ubuntu
Installation on Debian/Ubuntu distributions needs that the APT repository be added to the sources
list.
wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O
/etc/apt/sources.list.d/d-apt.list
wget -qO - https://dlang.org/d-keyring.gpg | sudo apt-key add -
apt-get update
apt-get install dmd-bin
Other compilers
LDC is a D compiler thats uses the oficial DMD compiler frontend and LLVM as its backend.
IDEs
In order to make life easier you may also want to install an IDE (Integrated Development
Environment). The D-Language Wiki has a list of available IDEs and Plugins for all Platforms here.
Hello World
import std.stdio;
To compile and run, save this text as a file called main.d. From the command line run dmd main.d to
compile the program. Finally, run ./main to execute the program in a bash shell or you can click on
the executable on windows.
Hello, World!
To create the classic "Hello, world" printing program, create a file called hello.d with a text editor
containing the following code :
import std.stdio;
void main() {
https://riptutorial.com/ 3
writeln("Hello, World!"); //writeln() automatically adds a newline (\n) to the output
}
Explanation :
import std.stdio
This line tells the compiler that functions defined in the Standard Library module std.stdio will be
used. Any module may be imported, as long as the compiler knows where to look for them. Many
functions are provided as part of D's massive Standard Library.
void main() {
This line declares the function main, returning void. Note that unlike C and C++, D allows main to
be of type void. The function main is special as it is the entry point of the program, i.e., this is where
the execution of the program begins. A few notes about functions in general :
• A function's name can be anything that starts with a letter and is composed of letters, digits
and underscores.
• Expected parameters will be a comma-separated list of variable names and their data types.
• The value that the function is expected to return can be any existing data type, and it must
match the type of expression used in the return statement within the function.
The curly braces { … } are used in pairs to indicate where a block of code begins and ends. They
can be used in a lot of ways, but in this case they indicate where the function begins and ends.
writeln("Hello, World!");
writeln is a function declared in std.stdio that writes its agruments to stdout. In this case, its
argument is "Hello, World", which will be written to the console. Various format characters, similar
to the ones used by C's printf may be used, like \n, \r, etc.
Comments are used to indicate something to the person reading the code and are treated like a
blank by the compiler. In the code above, this is a comment:
These are pieces of code that are ignored by the compiler. There are three different ways to
comment in D :
https://riptutorial.com/ 4
They are very useful to convey what a function / piece of code is doing to a fellow developer.
To compile using DMD, the reference D compiler, open a terminal, navigate to the the location of
the file hello.d that you created and then run :
dmd hello.d
If no errors are found, the compiler will output an executable named after your source file. This can
now be run by typing
./hello
Upon execution, the program will print out Hello, World!, followed by a newline.
import std.format;
void main() {
string s = "Name Surname 18";
string name, surname;
int age;
formattedRead(s, "%s %s %s", &name, &surname, &age);
// %s selects a format based on the corresponding argument's type
}
https://riptutorial.com/ 5
Chapter 2: Associative Arrays
Examples
Standard use
void main() {
int[string] count = wordCount(["hello", "world", "I", "say", "hello"]);
foreach (key; count.keys) {
writefln("%s: %s", key, count[key]);
}
// hello: 2
// world: 1
// I: 1
// say: 1
Literals
Items can be removed by using .remove(), if key exits will be removed and remove returns true:
https://riptutorial.com/ 6
assert(aa.remove("x"));
if the given key does not exist remove does nothing and returns false:
assert(!aa.remove("z"));
assert("a" in numbers);
assert("b" in numbers);
assert("c" in numbers);
https://riptutorial.com/ 7
Chapter 3: Classes
Syntax
• class Foo { } // inherits from Object
• class Bar: Foo { } // Bar is a Foo too
• Foo f = new Foo(); // instantiate new objects on the heap
Remarks
See the specification, browse a book chapter on classes, inheritance and play interactively.
Examples
Inheritance
class Animal
{
abstract int maxSize(); // must be implemented by sub-class
final float maxSizeInMeters() // can't be overridden by base class
{
return maxSize() / 100.0;
}
}
void main()
{
import std.stdio : writeln;
auto l = new Lion();
assert(l.maxSizeInMeters() == 3.5);
writeln(l.maxSizeInMeters()); // 3.5
}
Instantiation
class Lion
{
private double weight; // only accessible with-in class
this(double weight)
{
this.weight = weight;
}
https://riptutorial.com/ 8
double weightInPounds() const @property // const guarantees no modifications
// @property functions are treated as fields
{
return weight * 2.204;
}
}
void main()
{
import std.stdio : writeln;
auto l = new Lion(100);
assert(l.weightInPounds == 220.4);
writeln(l.weightInPounds); // 220.4
}
https://riptutorial.com/ 9
Chapter 4: Compile Time Function Evaluation
(CTFE)
Remarks
CTFE is a mechanism which allows the compiler to execute functions at compile time. There is no
special set of the D language necessary to use this feature - whenever a function just depends on
compile time known values the D compiler might decide to interpret it during compilation.
Examples
Evaluate a function at compile-time
long fib(long n)
{
return n < 2 ? n : fib(n - 1) + fib(n - 2);
}
void main()
{
import std.stdio : writeln;
enum f10 = fib(10); // execute the function at compile-time
pragma(msg, f10); // will print 55 during compile-time
writeln(f10); // print 55 during runtime
pragma(msg, FibStruct!11.sizeof); // The size of the struct is 89
}
https://riptutorial.com/ 10
Chapter 5: Contracts
Remarks
The assertions will be optimized away in an release build.
Examples
Function contracts
Function contracts allow the programer to check for inconsistencies. Inconsistencies include
invalid parameters, checks for the correct return value or an invalid state of the object.
The checks can happen before and after the body of the function or method is executed.
Function contracts
For example if an method is invoked the state of the object may not allow that a method is called
with specific parameters or not at all.
class OlderThanEighteen {
uint age;
https://riptutorial.com/ 11
Chapter 6: Dynamic Arrays & Slices
Syntax
• <type>[] <name>;
Remarks
Slices generate a new view on existing memory. They don't create a new copy. If no slice holds a
reference to that memory anymore - or a sliced part of it - it will be freed by the garbage collector.
Using slices it's possible to write very efficient code for e.g. parsers that just operate on one
memory block and just slice the parts they really need to work on - no need allocating new
memory blocks.
Examples
Declaration and initialization
import std.stdio;
void main() {
int[] arr = [1, 2, 3, 4];
writeln(arr.length); // 4
writeln(arr[2]); // 3
Array operations
import std.stdio;
void main() {
int[] arr = [1, 2, 3];
// concatenate
arr ~= 4;
writeln(arr); // [1, 2, 3, 4]
Slices
https://riptutorial.com/ 12
import std.stdio;
void main() {
int[] arr = [1, 2, 3, 4, 5];
auto arr2 = arr[1..$ - 1]; // .. is the slice syntax, $ represents the length of the array
writeln(arr2); // [2, 3, 4]
arr2[0] = 42;
writeln(arr[1]); // 42
}
https://riptutorial.com/ 13
Chapter 7: Imports and modules
Syntax
• module my.package;
• import my.package;
• import my.package : function;
• import fancyName = mypackage;
• import my.package : fancyFunctionName = function;
Remarks
Modules automatically provide a namespace scope for their contents. Modules superficially
resemble classes, but differ in that:
• The order in which modules are imported does not affect the semantics.
• The semantics of a module are not affected by what imports it.
• If a module C imports modules A and B, any modifications to B will not silently change code
in C that is dependent on A.
Examples
Global imports
import std.stdio;
void main()
{
writeln("Hello World!");
}
Multiple imports can either be specified in the same line, separated with a comma or in a new line.
https://riptutorial.com/ 14
{
writeln("2^4: ", pow(2, 4));
writeln("Current time: ", Clock.currTime());
}
Selective imports
Selective imports can help to cleanup the namespace and speed-up the compile-time even more,
because the compiler only needs to parse the specific, selected functions.
Local imports
You can also import symbols in any scope, the import will only be looked up when the scope is
needed (i.e. compiled) and the imported names will only be exposed in the imported scope. Most
commonly the scope for local imports are functions, structs and classes.
void main()
{
import std.stdio: writeln;
writeln("Hello world");
}
// writeln isn't defined here
Public imports
Renamed imports
A local name for an import can be given, through which all references to the module's symbols
must be qualified with:
import io = std.stdio;
void main()
{
io.writeln("Hello world");
std.stdio.writeln("hello!"); // error, std is undefined
writeln("hello!"); // error, writeln is undefined
}
https://riptutorial.com/ 15
Renamed imports are handy when dealing with very long import names.
void main()
{
import std.stdio : fooln = writeln;
fooln("Hello world");
}
Module declaration
Modules have a one-to-one correspondence with source files. The module name is, by default, the
file name with the path and extension stripped off, and can be set explicitly with the module
declaration. The ModuleDeclaration sets the name of the module and what package it belongs to. If
absent, the module name is taken to be the same name (stripped of path and extension) of the
source file name.
module my.fancy.module;
https://riptutorial.com/ 16
Chapter 8: Loops
Syntax
• for (<initializer>; <loop condition>; <loop statement>) { <statements> }
• while (<condition>) { <statements> }
• do { <statements> } while (<condition>);
• foreach (<el>, <collection>)
• foreach_reverse (<el>, <collection>)
Remarks
• for loop in Programming in D, specification
• while loop in Programming in D, specification
• do while loop in Programming in D, specification
• foreach in Programming in D, opApply, specification
Examples
For loop
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
for (int i = 0; i < arr.length; i++)
{
arr[i] *= 2;
}
writeln(arr); // [2, 6, 8]
}
While loop
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
int i = 0;
while (i < arr.length)
{
arr[i++] *= 2;
}
writeln(arr); // [2, 6, 8]
}
https://riptutorial.com/ 17
do-while
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
int i = 0;
assert(arr.length > 0, "Array must contain at least one element");
do
{
arr[i++] *= 2;
} while (i < arr.length);
writeln(arr); // [2, 6, 8]
}
Foreach
Foreach allows a less error-prone and better readable way to iterate collections. The attribute ref
can be used if we want to directly modify the iterated element.
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
foreach (ref el; arr)
{
el *= 2;
}
writeln(arr); // [2, 6, 8]
}
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
foreach (i, el; arr)
{
arr[i] = el * 2;
}
writeln(arr); // [2, 6, 8]
}
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
int i = 0;
foreach_reverse (ref el; arr)
{
el += i++; // 4 is incremented by 0, 3 by 1, and 1 by 2
}
https://riptutorial.com/ 18
writeln(arr); // [3, 4, 4]
}
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4, 5];
foreach (i, el; arr)
{
if (i == 0)
continue; // continue with the next iteration
arr[i] *= 2;
if (i == 2)
break; // stop the loop iteration
}
writeln(arr); // [1, 6, 8, 5]
}
void main()
{
import std.stdio : writeln;
int[] arr = [1, 3, 4];
outer: foreach (j; 0..10) // iterates with j=0 and j=1
foreach (i, el; arr)
{
arr[i] *= 2;
if (j == 1)
break outer; // stop the loop iteration
}
writeln(arr); // [4, 6, 8] (only 1 reaches the second iteration)
}
https://riptutorial.com/ 19
Chapter 9: Memory & Pointers
Syntax
• &<variable> - access by reference (=gets the pointer to the data of the variable)
• *<variable> - deference operator (=gets the data object from a pointer)
• <type>* - data type that points to <type> (e.g. `int*)
Examples
Pointers
D is a system programming language and thus allows you to manually manage and mess up your
memory. Nevertheless, D uses a garbage collector per default to free unused memory.
void main()
{
int a;
int* b = &a; // b contains address of a
auto c = &a; // c is int* and contains address of a
A new memory block on the heap is allocated using the new expression, which returns a pointer to
the managed memory:
void main()
{
int* a = new int;
*a = 42; // dereferencing
import std.stdio : writeln;
writeln("a: ", *a);
}
@safe D
As soon as the memory referenced by a isn't referenced anymore through any variable in the
program, the garbage collector will free its memory.
https://riptutorial.com/ 20
void safeFun() @safe
{
writeln("Hello World");
// allocating memory with the GC is safe too
int* p = new int;
}
void unsafeFun()
{
int* p = new int;
int* fiddling = p + 5;
}
void main()
{
safeFun();
unsafeFun();
}
For more information about SafeD see the article from the D design team.
https://riptutorial.com/ 21
Chapter 10: Ranges
Remarks
If a foreach is encountered by the compiler
Any object which fulfills the above interface is called an input range and is thus a type that can be
iterated over:
struct InputRange {
@property bool empty();
@property T front();
void popFront();
}
Examples
Strings and arrays are ranges
import std.stdio;
void main() {
auto s = "hello world";
auto a = [1, 2, 3, 4];
foreach (c; s) {
write(c, "!"); // h!e!l!l!o! !w!o!r!l!d!
}
writeln();
foreach (x; a) {
write(x * x, ", "); // 1, 4, 9, 16,
}
}
struct InputRange(T) {
https://riptutorial.com/ 22
@property bool empty();
@property T front();
void popFront();
}
In short, a way to
To make our own type a InputRange, we must implement these three functions. Let's take a look at
the infinite sequence of squares.
struct SquaresRange {
int cur = 1;
void popFront() {
cur++;
}
}
https://riptutorial.com/ 23
Chapter 11: Scope guards
Syntax
• scope(exit) - statements are called no matter how the current block was exited
• scope(success) - statements are called when the current block was exited normally
• scope(failure) - statements are called when the current block was exited through exception
throwing
Remarks
Using scope guards makes code much cleaner and allows to place resource allocation and clean
up code next to each other. These little helpers also improve safety because they make sure
certain cleanup code is always called independent of which paths are actually taken at runtime.
The D scope feature effectively replaces the RAII idiom used in C++ which often leads to special
scope guards objects for special resources.
Scope guards are called in the reverse order they are defined.
Examples
Place allocation and cleanup code next to each other
Scope guards allow executing statements at certain conditions if the current block is left.
import core.stdc.stdlib;
void main() {
int* p = cast(int*)malloc(int.sizeof);
scope(exit) free(p);
}
import std.stdio;
void main() {
writeln("<html>");
scope(exit) writeln("</html>");
{
writeln("\t<head>");
scope(exit) writeln("\t</head>");
"\t\t<title>%s</title>".writefln("Hello");
} // the scope(exit) on the previous line is executed here
https://riptutorial.com/ 24
writeln("\t<body>");
scope(exit) writeln("\t</body>");
writeln("\t\t<h1>Hello World!</h1>");
}
prints
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
https://riptutorial.com/ 25
Chapter 12: Strings
Remarks
• Strings in D are immutable; use .dup to make a mutable char array if you want to edit in-
place.
Examples
Reversing a string
string is defined as alias string = immutable(char)[];: so need to use dup to make a mutable char
array, before it can be reversed:
import std.stdio;
import std.string;
int main() {
return 0;
Empty string
Empty string is not null but has zero length:
Null string
string nullString = null;
https://riptutorial.com/ 26
a null string is null (De Lapalisse)
assert(nullString is null);
but, unlike C#, read the length of a null string does not generate error:
assert(nullString.length == 0);
assert(nullString.empty);
if (emptyOrNullString.length == 0) {
}
// or
if (emptyOrNullString.length) {
}
// or
import std.array;
if (emptyOrNullString.empty) {
}
References
• What is the correct way to test for an empty string?
• Does D has C#'s string.Empty?
string s = "unogatto";
immutable(ubyte[]) ustr = cast(immutable(ubyte)[])s;
assert(typeof(ustr).stringof == "immutable(ubyte[])");
assert(ustr.length == 8);
assert(ustr[0] == 0x75); //u
assert(ustr[1] == 0x6e); //n
https://riptutorial.com/ 27
assert(ustr[2] == 0x6f); //o
assert(ustr[3] == 0x67); //g
assert(ustr[7] == 0x6f); //o
String to ubyte[]
string s = "unogatto";
ubyte[] mustr = cast(ubyte[])s;
assert(typeof(mustr).stringof == "ubyte[]");
assert(mustr.length == 8);
assert(mustr[0] == 0x75);
assert(mustr[1] == 0x6e);
assert(mustr[2] == 0x6f);
assert(mustr[3] == 0x67);
assert(mustr[7] == 0x6f);
ubyte[] to string
ubyte[] stream = [ 0x75, 0x6e, 0x6f, 0x67];
string us = cast(string)stream;
assert(us == "unog");
References
• DLang forum
https://riptutorial.com/ 28
Chapter 13: Structs
Examples
Defining a new Struct
To define the struct called Person with an integer type variable age, integer type variable height
and float type variable ageXHeight:
struct Person {
int age;
int height;
float ageXHeight;
}
Generally:
struct structName {
/+ values go here +/
}
Struct Constructors
In D we can use constructors to initialize structs just like a class. To define a construct for the
struct declared in the previous example we can type:
struct Person {
this(int age, int height) {
this.age = age;
this.height = height;
this.ageXHeight = cast(float)age * height;
}
}
https://riptutorial.com/ 29
Chapter 14: Templates
Syntax
• template identifier (TemplateParameterList) { ... }
• struct identifier (TemplateParameterList) { ... }
• class identifier (TemplateParameterList) { ... }
• ReturnType identifier (TemplateParameterList)(ParameterList) { ... }
• identifier!(TemplateInvocationList)
Examples
Function with one template
import std.stdio;
void main() {
//Automatic type inference
writeln(min(1, 2));
//Explicit type
writeln(min!(ubyte)(1, 2));
template
An template can be introduced with template. It can contain functions and classes and other
constructs.
size_t myLength() {
return getLength(this);
}
}
void main() {
https://riptutorial.com/ 30
StaticArray!(int, 5) arr5 = new StaticArray!(int, 5);
import std.stdio;
writeln(arr5.myLength());
}
https://riptutorial.com/ 31
Chapter 15: Traits
Syntax
• __traits (TraitsKeyword, TraitsArguments...)
Examples
Iterating over the members of a struct
import std.stdio;
struct A {
int b;
void c();
string d;
};
void main() {
// The following foreach is unrolled in compile time
foreach(name; __traits(allMembers, A)) {
pragma(msg, name);
}
}
The allMembers traits returns a tuple of string containing the names of the members of the given
type. These strings are known at compile time.
module main;
return members;
}
class Foo {
int a;
int b;
}
https://riptutorial.com/ 32
void main() {
import std.stdio;
derivedMembers returns a tuple of string literals, where each string is the member name.
c
d
e
https://riptutorial.com/ 33
Chapter 16: UFCS - Uniform Function Call
Syntax
Syntax
• aThirdFun(anotherFun(myFun(), 42); // common notation (also valid)
• myFun().anotherFun(42).aThirdFun(); // UFCS
• myFun.anotherFun(42).aThirdFun; // empty braces can be removed
Remarks
In a call a.b(args...), if the type a does not have a method named b, then the compiler will try to
rewrite the call as b(a, args...).
Examples
Checking if a Number is Prime
import std.stdio;
return true;
}
void main() {
writeln(2.isPrime);
writeln(3.isPrime);
writeln(4.isPrime);
5.isPrime.writeln;
}
void main() {
import std.algorithm : group;
import std.range;
[1, 2].chain([3, 4]).retro; // [4, 3, 2, 1]
[1, 1, 2, 2, 2].group.dropOne.front; // tuple(2, 3u)
}
https://riptutorial.com/ 34
import core.thread, std.stdio, std.datetime;
void some_operation() {
// Sleep for two sixtieths (2/60) of a second.
Thread.sleep(2.seconds / 60);
// Sleep for 100 microseconds.
Thread.sleep(100.usecs);
}
void main() {
MonoTime t0 = MonoTime.currTime();
some_operation();
MonoTime t1 = MonoTime.currTime();
Duration time_taken = t1 - t0;
https://riptutorial.com/ 35
Chapter 17: Unittesting
Syntax
• unittest { ... } - a block that is only run in "unittesting" mode
• assert(<expression that evaluates to a boolean>, <optional error message>)
Examples
Unittest blocks
Tests are an excellent way to ensure stable, bug-free applications. They serve as an interactive
documentation and allow to modify code without fear to break functionality. D provides a
convenient and native syntax for unittest block as part of the D language. Anywhere in a D
module unittest blocks can be used to test functionality of the source code.
/**
Yields the sign of a number.
Params:
n = number which should be used to check the sign
Returns:
1 for positive n, -1 for negative and 0 for 0.
*/
T sgn(T)(T n)
{
if (n == 0)
return 0;
return (n > 0) ? 1 : -1;
}
Executing unittest
If -unittest flag is passed to the D compiler, it will run all unittest blocks. Often it is useful to let the
compiler generate a stubbed main function. Using the compile & run wrapper rdmd, testing your D
program gets as easy as:
Of course you can also split this process into two steps if you want:
https://riptutorial.com/ 36
dmd -main -unittest yourcode.d
./yourcode
For dub projects compiling all files and executing their unittest blocks can be done conveniently
with
dub test
tdmd yourcode.d
Annotated unittest
For templated code it is often useful to verify that for function attributes (e.g. @nogc are inferred
correctly. To ensure this for a specific test and thus type the entire unittest can be annotated
Note that of course in D every block can be annotated with attributes and the compilers, of course,
verifies that they are correct. So for example the following would be similar to the example above:
unittest
{
import std.math;
@safe {
assert(exp(0) == 1);
assert(log(1) == 0);
}
}
https://riptutorial.com/ 37
Credits
S.
Chapters Contributors
No
Compile Time
4 Function Evaluation André Puel, greenify
(CTFE)
5 Contracts Quonux
UFCS - Uniform
16 André Puel, greenify, tre0n
Function Call Syntax
17 Unittesting greenify
https://riptutorial.com/ 38