D Programming – Literals

D Programming – Literals ”; Previous Next Constant values that are typed in the program as a part of the source code are called literals. Literals can be of any of the basic data types and can be divided into Integer Numerals, Floating-Point Numerals, Characters, Strings, and Boolean Values. Again, literals are treated just like regular variables except that their values cannot be modified after their definition. Integer Literals An integer literal can be a of the following types − Decimal uses the normal number represention with the first digit cannot be 0 as that digit is reserved for indicating the octal system.This does not include 0 on its own: 0 is zero. Octal uses 0 as prefix to number. Binary uses 0b or 0B as prefix. Hexadecimal uses 0x or 0X as prefix. An integer literal can also have a suffix that is a combination of U and L, for unsigned and long, respectively. The suffix can be uppercase or lowercase and can be in any order. When you don’t use a suffix, the compiler itself chooses between int, uint, long, and ulong based on the magnitude of the value. Here are some examples of integer literals − 212 // Legal 215u // Legal 0xFeeL // Legal 078 // Illegal: 8 is not an octal digit 032UU // Illegal: cannot repeat a suffix Following are other examples of various types of integer literals − 85 // decimal 0213 // octal 0x4b // hexadecimal 30 // int 30u // unsigned int 30l // long 30ul // unsigned long 0b001 // binary Floating Point Literals The floating point literals can be specified in either the decimal system as in 1.568 or in the hexadecimal system as in 0x91.bc. In the decimal system, an exponent can be represented by adding the character e or E and a number after that. For example, 2.3e4 means “2.3 times 10 to the power of 4”. A “+” character may be specified before the value of the exponent, but it has no effect. For example 2.3e4 and 2.3e + 4 are the same. The “-” character added before the value of the exponent changes the meaning to be “divided by 10 to the power of”. For example, 2.3e-2 means “2.3 divided by 10 to the power of 2”. In the hexadecimal system, the value starts with either 0x or 0X. The exponent is specified by p or P instead of e or E. The exponent does not mean “10 to the power of”, but “2 to the power of”. For example, the P4 in 0xabc.defP4 means “abc.de times 2 to the power of 4”. Here are some examples of floating-point literals − 3.14159 // Legal 314159E-5L // Legal 510E // Illegal: incomplete exponent 210f // Illegal: no decimal or exponent .e55 // Illegal: missing integer or fraction 0xabc.defP4 // Legal Hexa decimal with exponent 0xabc.defe4 // Legal Hexa decimal without exponent. By default, the type of a floating point literal is double. The f and F mean float, and the L specifier means real. Boolean Literals There are two Boolean literals and they are part of standard D keywords − A value of true representing true. A value of false representing false. You should not consider the value of true equal to 1 and value of false equal to 0. Character Literals Character literals are enclosed in single quotes. A character literal can be a plain character (e.g., ”x”), an escape sequence (e.g., ”t”), ASCII character (e.g., ”x21”), Unicode character (e.g., ”u011e”) or as named character (e.g. ”&copy”,”♥”, ”€” ). There are certain characters in D when they are preceded by a backslash they will have special meaning and they are used to represent like newline (n) or tab (t). Here, you have a list of some of such escape sequence codes − Escape sequence Meaning \ character ” ” character “ ” character ? ? character a Alert or bell b Backspace f Form feed n Newline r Carriage return t Horizontal tab v Vertical tab The following example shows few escape sequence characters − Live Demo import std.stdio; int main(string[] args) { writefln(“HellotWorld%cn”,”x21”); writefln(“Have a good day%c”,”x21”); return 0; } When the above code is compiled and executed, it produces the following result − Hello World! Have a good day! String Literals String literals are enclosed in double quotes. A string contains characters that are similar to character literals: plain characters, escape sequences, and universal characters. You can break a long line into multiple lines using string literals and separate them using whitespaces. Here are some examples of string literals − import std.stdio; int main(string[] args) { writeln(q”MY_DELIMITER Hello World Have a good day MY_DELIMITER”); writefln(“Have a good day%c”,”x21”); auto str = q{int value = 20; ++value;}; writeln(str); } In the above example, you can find the use of q”MY_DELIMITER MY_DELIMITER” to represent multi line characters. Also, you can see q{} to represent an D language statement itself. Print Page Previous Next Advertisements ”;

D Programming – Ranges

D Programming – Ranges ”; Previous Next Ranges are an abstraction of element access. This abstraction enables the use of great number of algorithms over great number of container types. Ranges emphasize how container elements are accessed, as opposed to how the containers are implemented. Ranges is a very simple concept that is based on whether a type defines certain sets of member functions. Ranges are an integral part of D. D”s slices happen to be implementations of the most powerful range RandomAccessRange, and there are many range features in Phobos. Many Phobos algorithms return temporary range objects. For example, filter() chooses elements that are greater than 10 in the following code actually returns a range object, not an array. Number ranges Number ranges are quite commonly used and these number ranges is of type int. A few examples for number ranges is shown below − // Example 1 foreach (value; 3..7) // Example 2 int[] slice = array[5..10]; Phobos Ranges Ranges related to structs and class interfaces is phobos ranges. Phobos is the official runtime and standard library that comes with the D language compiler. There are various types of ranges which include − InputRange ForwardRange BidirectionalRange RandomAccessRange OutputRange InputRange The simplest range is the input range. The other ranges bring more requirements on top of the range that they are based on. There are three functions that InputRange requires − empty − It specifies whether the range is empty; it must return true when the range is considered to be empty; false otherwise. front − It provides access to the element at the beginning of the range. popFront() − It shortens the range from the beginning by removing the first element. Example Live Demo import std.stdio; import std.string; struct Student { string name; int number; string toString() const { return format(“%s(%s)”, name, number); } } struct School { Student[] students; } struct StudentRange { Student[] students; this(School school) { this.students = school.students; } @property bool empty() const { return students.length == 0; } @property ref Student front() { return students[0]; } void popFront() { students = students[1 .. $]; } } void main() { auto school = School([ Student(“Raj”, 1), Student(“John”, 2), Student(“Ram”, 3)]); auto range = StudentRange(school); writeln(range); writeln(school.students.length); writeln(range.front); range.popFront; writeln(range.empty); writeln(range); } When the above code is compiled and executed, it produces the following result − [Raj(1), John(2), Ram(3)] 3 Raj(1) false [John(2), Ram(3)] ForwardRange ForwardRange additionally requires the save member function part from the other three function of InputRange and return a copy of the range when the save function is called. Live Demo import std.array; import std.stdio; import std.string; import std.range; struct FibonacciSeries { int first = 0; int second = 1; enum empty = false; // infinite range @property int front() const { return first; } void popFront() { int third = first + second; first = second; second = third; } @property FibonacciSeries save() const { return this; } } void report(T)(const dchar[] title, const ref T range) { writefln(“%s: %s”, title, range.take(5)); } void main() { auto range = FibonacciSeries(); report(“Original range”, range); range.popFrontN(2); report(“After removing two elements”, range); auto theCopy = range.save; report(“The copy”, theCopy); range.popFrontN(3); report(“After removing three more elements”, range); report(“The copy”, theCopy); } When the above code is compiled and executed, it produces the following result − Original range: [0, 1, 1, 2, 3] After removing two elements: [1, 2, 3, 5, 8] The copy: [1, 2, 3, 5, 8] After removing three more elements: [5, 8, 13, 21, 34] The copy: [1, 2, 3, 5, 8] BidirectionalRange BidirectionalRange additionally provides two member functions over the member functions of ForwardRange. The back function which is similar to front, provides access to the last element of the range. The popBack function is similar to popFront function and it removes the last element from the range. Example Live Demo import std.array; import std.stdio; import std.string; struct Reversed { int[] range; this(int[] range) { this.range = range; } @property bool empty() const { return range.empty; } @property int front() const { return range.back; // reverse } @property int back() const { return range.front; // reverse } void popFront() { range.popBack(); } void popBack() { range.popFront(); } } void main() { writeln(Reversed([ 1, 2, 3])); } When the above code is compiled and executed, it produces the following result − [3, 2, 1] Infinite RandomAccessRange opIndex() is additionally required when compared to the ForwardRange. Also, the value of an empty function to be known at compile time as false. A simple example is explained with squares range is shown below. Live Demo import std.array; import std.stdio; import std.string; import std.range; import std.algorithm; class SquaresRange { int first; this(int first = 0) { this.first = first; } enum empty = false; @property int front() const { return opIndex(0); } void popFront() { ++first; } @property SquaresRange save() const { return new SquaresRange(first); } int opIndex(size_t index) const { /* This function operates at constant time */ immutable integerValue = first + cast(int)index; return integerValue * integerValue; } } bool are_lastTwoDigitsSame(int value) { /* Must have at least two digits */ if (value < 10) { return false; } /* Last two digits must be divisible by 11 */ immutable lastTwoDigits = value % 100; return (lastTwoDigits % 11) == 0; } void main() { auto squares = new SquaresRange(); writeln(squares[5]); writeln(squares[10]); squares.popFrontN(5); writeln(squares[0]); writeln(squares.take(50).filter!are_lastTwoDigitsSame); } When the above code is compiled and executed, it produces the following result − 25 100 25 [100, 144, 400, 900, 1444, 1600, 2500] Finite RandomAccessRange opIndex() and length are additionally required when compared to bidirectional range. This is explained with the help of detailed example that uses the Fibonacci series and Squares Range example used earlier. This example works well on normal D compiler but does not work on online compiler. Example Live Demo import std.array; import std.stdio; import std.string; import std.range; import std.algorithm; struct FibonacciSeries { int first = 0; int second = 1; enum empty = false; // infinite

D Programming – Variables

D Programming – Variables ”; Previous Next A variable is nothing but a name given to a storage area that our programs can manipulate. Each variable in D has a specific type, which determines the size and layout of the variable”s memory; the range of values that can be stored within that memory; and the set of operations that can be applied to the variable. The name of a variable can be composed of letters, digits, and the underscore character. It must begin with either a letter or an underscore. Upper and lowercase letters are distinct because D is case-sensitive. Based on the basic types explained in the previous chapter, there will be the following basic variable types − Sr.No. Type & Description 1 char Typically a single octet (one byte). This is an integer type. 2 int The most natural size of integer for the machine. 3 float A single-precision floating point value. 4 double A double-precision floating point value. 5 void Represents the absence of type. D programming language also allows to define various other types of variables such as Enumeration, Pointer, Array, Structure, Union, etc., which we will cover in subsequent chapters. For this chapter, let us study only basic variable types. Variable Definition in D A variable definition tells the compiler where and how much space to create for the variable. A variable definition specifies a data type and contains a list of one or more variables of that type as follows − type variable_list; Here, type must be a valid D data type including char, wchar, int, float, double, bool, or any user-defined object, etc., and variable_list may consist of one or more identifier names separated by commas. Some valid declarations are shown here − int i, j, k; char c, ch; float f, salary; double d; The line int i, j, k; both declares and defines the variables i, j and k; which instructs the compiler to create variables named i, j, and k of type int. Variables can be initialized (assigned an initial value) in their declaration. The initializer consists of an equal sign followed by a constant expression as follows − type variable_name = value; Examples extern int d = 3, f = 5; // declaration of d and f. int d = 3, f = 5; // definition and initializing d and f. byte z = 22; // definition and initializes z. char x = ”x”; // the variable x has the value ”x”. When a variable is declared in D, it is always set to its ”default initializer”, which can be manually accessed as T.init where T is the type (ex. int.init). The default initializer for integer types is 0, for Booleans false, and for floating-point numbers NaN. Variable Declaration in D A variable declaration provides assurance to the compiler that there is one variable existing with the given type and name so that compiler proceed for further compilation without needing complete detail about the variable. A variable declaration has its meaning at the time of compilation only, compiler needs actual variable declaration at the time of linking of the program. Example Try the following example, where variables have been declared at the start of the program, but are defined and initialized inside the main function − Live Demo import std.stdio; int a = 10, b = 10; int c; float f; int main () { writeln(“Value of a is : “, a); /* variable re definition: */ int a, b; int c; float f; /* Initialization */ a = 30; b = 40; writeln(“Value of a is : “, a); c = a + b; writeln(“Value of c is : “, c); f = 70.0/3.0; writeln(“Value of f is : “, f); return 0; } When the above code is compiled and executed, it produces the following result − Value of a is : 10 Value of a is : 30 Value of c is : 70 Value of f is : 23.3333 Lvalues and Rvalues in D There are two kinds of expressions in D − lvalue − An expression that is an lvalue may appear as either the left-hand or right-hand side of an assignment. rvalue − An expression that is an rvalue may appear on the right- but not left-hand side of an assignment. Variables are lvalues and so may appear on the left-hand side of an assignment. Numeric literals are rvalues and so may not be assigned and cannot appear on the left-hand side. The following statement is valid − int g = 20; But the following is not a valid statement and would generate a compile-time error − 10 = 20; Print Page Previous Next Advertisements ”;

D Programming – Functions

D Programming – Functions ”; Previous Next This chapter describes the functions used in D programming. Function Definition in D A basic function definition consists of a function header and a function body. Syntax return_type function_name( parameter list ) { body of the function } Here are all the parts of a function − Return Type − A function may return a value. The return_type is the data type of the value the function returns. Some functions perform the desired operations without returning a value. In this case, the return_type is the keyword void. Function Name − This is the actual name of the function. The function name and the parameter list together constitute the function signature. Parameters − A parameter is like a placeholder. When a function is invoked, you pass a value to the parameter. This value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the parameters of a function. Parameters are optional; that is, a function may contain no parameters. Function Body − The function body contains a collection of statements that define what the function does. Calling a Function You can a call a function as follows − function_name(parameter_values) Function Types in D D programming supports a wide range of functions and they are listed below. Pure Functions Nothrow Functions Ref Functions Auto Functions Variadic Functions Inout Functions Property Functions The various functions are explained below. Pure Functions Pure functions are functions which cannot access global or static, mutable state save through their arguments. This can enable optimizations based on the fact that a pure function is guaranteed to mutate nothing which is not passed to it, and in cases where the compiler can guarantee that a pure function cannot alter its arguments, it can enable full, functional purity, that is, the guarantee that the function will always return the same result for the same arguments). Live Demo import std.stdio; int x = 10; immutable int y = 30; const int* p; pure int purefunc(int i,const char* q,immutable int* s) { //writeln(“Simple print”); //cannot call impure function ”writeln” debug writeln(“in foo()”); // ok, impure code allowed in debug statement // x = i; // error, modifying global state // i = x; // error, reading mutable global state // i = *p; // error, reading const global state i = y; // ok, reading immutable global state auto myvar = new int; // Can use the new expression: return i; } void main() { writeln(“Value returned from pure function : “,purefunc(x,null,null)); } When the above code is compiled and executed, it produces the following result − Value returned from pure function : 30 Nothrow Functions Nothrow functions do not throw any exceptions derived from class Exception. Nothrow functions are covariant with throwing ones. Nothrow guarantees that a function does not emit any exception. import std.stdio; int add(int a, int b) nothrow { //writeln(“adding”); This will fail because writeln may throw int result; try { writeln(“adding”); // compiles result = a + b; } catch (Exception error) { // catches all exceptions } return result; } void main() { writeln(“Added value is “, add(10,20)); } When the above code is compiled and executed, it produces the following result − adding Added value is 30 Ref Functions Ref functions allow functions to return by reference. This is analogous to ref function parameters. Live Demo import std.stdio; ref int greater(ref int first, ref int second) { return (first > second) ? first : second; } void main() { int a = 1; int b = 2; greater(a, b) += 10; writefln(“a: %s, b: %s”, a, b); } When the above code is compiled and executed, it produces the following result − a: 1, b: 12 Auto Functions Auto functions can return value of any type. There is no restriction on what type to be returned. A simple example for auto type function is given below. Live Demo import std.stdio; auto add(int first, double second) { double result = first + second; return result; } void main() { int a = 1; double b = 2.5; writeln(“add(a,b) = “, add(a, b)); } When the above code is compiled and executed, it produces the following result − add(a,b) = 3.5 Variadic Functions Variadiac functions are those functions in which the number of parameters for a function is determined in runtime. In C, there is a limitation of having atleast one parameter. But in D programming, there is no such limitation. A simple example is shown below. Live Demo import std.stdio; import core.vararg; void printargs(int x, …) { for (int i = 0; i < _arguments.length; i++) { write(_arguments[i]); if (_arguments[i] == typeid(int)) { int j = va_arg!(int)(_argptr); writefln(“t%d”, j); } else if (_arguments[i] == typeid(long)) { long j = va_arg!(long)(_argptr); writefln(“t%d”, j); } else if (_arguments[i] == typeid(double)) { double d = va_arg!(double)(_argptr); writefln(“t%g”, d); } } } void main() { printargs(1, 2, 3L, 4.5); } When the above code is compiled and executed, it produces the following result − int 2 long 3 double 4.5 Inout Functions The inout can be used both for parameter and return types of functions. It is like a template for mutable, const, and immutable. The mutability attribute is deduced from the parameter. Means, inout transfers the deduced mutability attribute to the return type. A simple example showing how mutability gets changed is shown below. Live Demo import std.stdio; inout(char)[] qoutedWord(inout(char)[] phrase) { return ””” ~ phrase ~ ”””; } void main() { char[] a = “test a”.dup; a = qoutedWord(a); writeln(typeof(qoutedWord(a)).stringof,” “, a); const(char)[] b = “test b”; b = qoutedWord(b); writeln(typeof(qoutedWord(b)).stringof,” “, b); immutable(char)[] c = “test c”; c = qoutedWord(c); writeln(typeof(qoutedWord(c)).stringof,” “, c); } When the above code is compiled and executed, it produces the following result − char[] “test a” const(char)[] “test b” string “test c” Property Functions Properties allow using member functions like member variables. It uses the @property keyword. The properties are linked with

D Programming – Enums

D Programming – Enums ”; Previous Next An enumeration is used for defining named constant values. An enumerated type is declared using the enum keyword. The enum Syntax The simplest form of an enum definition is the following − enum enum_name { enumeration list } Where, The enum_name specifies the enumeration type name. The enumeration list is a comma-separated list of identifiers. Each of the symbols in the enumeration list stands for an integer value, one greater than the symbol that precedes it. By default, the value of the first enumeration symbol is 0. For example − enum Days { sun, mon, tue, wed, thu, fri, sat }; Example The following example demonstrates the use of enum variable − Live Demo import std.stdio; enum Days { sun, mon, tue, wed, thu, fri, sat }; int main(string[] args) { Days day; day = Days.mon; writefln(“Current Day: %d”, day); writefln(“Friday : %d”, Days.fri); return 0; } When the above code is compiled and executed, it produces the following result − Current Day: 1 Friday : 5 In the above program, we can see how an enumeration can be used. Initially, we create a variable named day of our user defined enumeration Days. Then we set it to mon using the dot operator. We need to use the writefln method to print the value of mon that is been stored. You also need specify the type. It is of the type integer, hence we use %d for printing. Named Enums Properties The above example uses a name Days for the enumeration and is called named enums. These named enums have the following properties − Init − It initializes the first value in the enumeration. min − It returns the smallest value of enumeration. max − It returns the largest value of enumeration. sizeof − It returns the size of storage for enumeration. Let us modify the previous example to make use of the properties. Live Demo import std.stdio; // Initialized sun with value 1 enum Days { sun = 1, mon, tue, wed, thu, fri, sat }; int main(string[] args) { writefln(“Min : %d”, Days.min); writefln(“Max : %d”, Days.max); writefln(“Size of: %d”, Days.sizeof); return 0; } When the above code is compiled and executed, it produces the following result − Min : 1 Max : 7 Size of: 4 Anonymous Enum Enumeration without name is called anonymous enum. An example for anonymous enum is given below. Live Demo import std.stdio; // Initialized sun with value 1 enum { sun , mon, tue, wed, thu, fri, sat }; int main(string[] args) { writefln(“Sunday : %d”, sun); writefln(“Monday : %d”, mon); return 0; } When the above code is compiled and executed, it produces the following result − Sunday : 0 Monday : 1 Anonymous enums work pretty much the same way as named enums but they do not have the max, min, and sizeof properties. Enum with Base Type Syntax The syntax for enumeration with base type is shown below. enum :baseType { enumeration list } Some of the base types includes long, int, and string. An example using long is shown below. Live Demo import std.stdio; enum : string { A = “hello”, B = “world”, } int main(string[] args) { writefln(“A : %s”, A); writefln(“B : %s”, B); return 0; } When the above code is compiled and executed, it produces the following result − A : hello B : world More Features Enumeration in D provides features like initialization of multiple values in an enumeration with multiple types. An example is shown below. Live Demo import std.stdio; enum { A = 1.2f, // A is 1.2f of type float B, // B is 2.2f of type float int C = 3, // C is 3 of type int D // D is 4 of type int } int main(string[] args) { writefln(“A : %f”, A); writefln(“B : %f”, B); writefln(“C : %d”, C); writefln(“D : %d”, D); return 0; } When the above code is compiled and executed, it produces the following result − A : 1.200000 B : 2.200000 C : 3 D : 4 Print Page Previous Next Advertisements ”;

D – Conditional Compilation

D Programming – Conditional Compilation ”; Previous Next Conditional compilation is the process of selecting which code to compile and which code to not compile similar to the #if / #else / #endif in C and C++. Any statement that is not compiled in still must be syntactically correct. Conditional compilation involves condition checks that are evaluable at compile time. Runtime conditional statements like if, for, while are not conditional compilation features. The following features of D are meant for conditional compilation − debug version static if Debug Statement in D The debug is useful during program development. The expressions and statements that are marked as debug are compiled into the program only when the -debug compiler switch is enabled. debug a_conditionally_compiled_expression; debug { // … conditionally compiled code … } else { // … code that is compiled otherwise … } The else clause is optional. Both the single expression and the code block above are compiled only when the -debug compiler switch is enabled. Instead of being removed altogether, the lines can be marked as debug instead. debug writefln(“%s debug only statement”, value); Such lines are included in the program only when the -debug compiler switch is enabled. dmd test.d -oftest -w -debug Debug (tag) Statement in D The debug statements can be given names (tags) to be included in the program selectively. debug(mytag) writefln(“%s not found”, value); Such lines are included in the program only when the -debug compiler switch is enabled. dmd test.d -oftest -w -debug = mytag The debug blocks can have tags as well. debug(mytag) { // } It is possible to enable more than one debug tag at a time. dmd test.d -oftest -w -debug = mytag1 -debug = mytag2 Debug (level) Statement in D Sometimes it is more useful to associate debug statements by numerical levels. Increasing levels can provide more detailed information. import std.stdio; void myFunction() { debug(1) writeln(“debug1”); debug(2) writeln(“debug2”); } void main() { myFunction(); } The debug expressions and blocks that are lower than or equal to the specified level would be compiled. $ dmd test.d -oftest -w -debug = 1 $ ./test debug1 Version (tag) and Version (level) Statements in D Version is similar to debug and is used in the same way. The else clause is optional. Although version works essentially the same as debug, having separate keywords helps distinguish their unrelated uses. As with debug, more than one version can be enabled. import std.stdio; void myFunction() { version(1) writeln(“version1”); version(2) writeln(“version2”); } void main() { myFunction(); } The debug expressions and blocks that are lower than or equal to the specified level would be compiled. $ dmd test.d -oftest -w -version = 1 $ ./test version1 Static if Static if is the compile time equivalent of the if statement. Just like the if statement, static if takes a logical expression and evaluates it. Unlike the if statement, static if is not about execution flow; rather, it determines whether a piece of code should be included in the program or not. The if expression is unrelated to the is operator that we have seen earlier, both syntactically and semantically. It is evaluated at compile time. It produces an int value, either 0 or 1; depending on the expression specified in parentheses. Although the expression that it takes is not a logical expression, the is expression itself is used as a compile time logical expression. It is especially useful in static if conditionals and template constraints. Live Demo import std.stdio; enum Days { sun, mon, tue, wed, thu, fri, sat }; void myFunction(T)(T mytemplate) { static if (is (T == class)) { writeln(“This is a class type”); } else static if (is (T == enum)) { writeln(“This is an enum type”); } } void main() { Days day; myFunction(day); } When we compile and run we will get some output as follows. This is an enum type Print Page Previous Next Advertisements ”;

D Programming – Concurrency

D Programming – Concurrency ”; Previous Next Concurrency is making a program run on multiple threads at a time. An example of a concurrent program is a web server responding many clients at the same time. Concurrency is easy with message passing but very difficult to write if they are based on data sharing. Data that is passed between threads are called messages. Messages may be composed of any type and any number of variables. Every thread has an id, which is used for specifying recipients of messages. Any thread that starts another thread is called the owner of the new thread. Initiating Threads in D The function spawn() takes a pointer as a parameter and starts a new thread from that function. Any operations that are carried out by that function, including other functions that it may call, would be executed on the new thread. The owner and the worker both start executing separately as if they were independent programs. Example import std.stdio; import std.stdio; import std.concurrency; import core.thread; void worker(int a) { foreach (i; 0 .. 4) { Thread.sleep(1); writeln(“Worker Thread “,a + i); } } void main() { foreach (i; 1 .. 4) { Thread.sleep(2); writeln(“Main Thread “,i); spawn(&ap;worker, i * 5); } writeln(“main is done.”); } When the above code is compiled and executed, it reads the file created in previous section and produces the following result − Main Thread 1 Worker Thread 5 Main Thread 2 Worker Thread 6 Worker Thread 10 Main Thread 3 main is done. Worker Thread 7 Worker Thread 11 Worker Thread 15 Worker Thread 8 Worker Thread 12 Worker Thread 16 Worker Thread 13 Worker Thread 17 Worker Thread 18 Thread Identifiers in D The thisTid variable available globally at the module level is always the id of the current thread. Also you can receive the threadId when spawn is called. An example is shown below. Example Live Demo import std.stdio; import std.concurrency; void printTid(string tag) { writefln(“%s: %s, address: %s”, tag, thisTid, &thisTid); } void worker() { printTid(“Worker”); } void main() { Tid myWorker = spawn(&worker); printTid(“Owner “); writeln(myWorker); } When the above code is compiled and executed, it reads the file created in previous section and produces the following result − Owner : Tid(std.concurrency.MessageBox), address: 10C71A59C Worker: Tid(std.concurrency.MessageBox), address: 10C71A59C Tid(std.concurrency.MessageBox) Message Passing in D The function send() sends messages and the function receiveOnly() waits for a message of a particular type. There are other functions named prioritySend(), receive(), and receiveTimeout(), which are explained later. The owner in the following program sends its worker a message of type int and waits for a message from the worker of type double. The threads continue sending messages back and forth until the owner sends a negative int. An example is shown below. Example Live Demo import std.stdio; import std.concurrency; import core.thread; import std.conv; void workerFunc(Tid tid) { int value = 0; while (value >= 0) { value = receiveOnly!int(); auto result = to!double(value) * 5; tid.send(result); } } void main() { Tid worker = spawn(&workerFunc,thisTid); foreach (value; 5 .. 10) { worker.send(value); auto result = receiveOnly!double(); writefln(“sent: %s, received: %s”, value, result); } worker.send(-1); } When the above code is compiled and executed, it reads the file created in previous section and produces the following result − sent: 5, received: 25 sent: 6, received: 30 sent: 7, received: 35 sent: 8, received: 40 sent: 9, received: 45 Message Passing with Wait in D A simple example with the message passing with wait is shown below. Live Demo import std.stdio; import std.concurrency; import core.thread; import std.conv; void workerFunc(Tid tid) { Thread.sleep(dur!(“msecs”)( 500 ),); tid.send(“hello”); } void main() { spawn(&workerFunc,thisTid); writeln(“Waiting for a message”); bool received = false; while (!received) { received = receiveTimeout(dur!(“msecs”)( 100 ), (string message) { writeln(“received: “, message); }); if (!received) { writeln(“… no message yet”); } } } When the above code is compiled and executed, it reads the file created in previous section and produces the following result − Waiting for a message … no message yet … no message yet … no message yet … no message yet received: hello Print Page Previous Next Advertisements ”;

D Programming – Immutables

D Programming – Immutable ”; Previous Next We often use variables that are mutable but there can be many occasions mutability is not required. Immutable variables can be used in such cases. A few examples are given below where immutable variable can be used. In case of math constants such as pi that never change. In case of arrays where we want to retain values and it is not requirements of mutation. Immutability makes it possible to understand whether the variables are immutable or mutable guaranteeing that certain operations do not change certain variables. It also reduces the risk of certain types of program errors. The immutability concept of D is represented by the const and immutable keywords. Although the two words themselves are close in meaning, their responsibilities in programs are different and they are sometimes incompatible. The immutability concept of D is represented by the const and immutable keywords. Although the two words themselves are close in meaning, their responsibilities in programs are different and they are sometimes incompatible. Types of Immutable Variables in D There are three types of defining variables that can never be mutated. enum constants immutable variables const variables enum Constants in D The enum constants makes it possible to relate constant values to meaningful names. A simple example is shown below. Example Live Demo import std.stdio; enum Day{ Sunday = 1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } void main() { Day day; day = Day.Sunday; if (day == Day.Sunday) { writeln(“The day is Sunday”); } } When the above code is compiled and executed, it produces the following result − The day is Sunday Immutable Variables in D Immutable variables can be determined during the execution of the program. It just directs the compiler that after the initialisation, it becomes immutable. A simple example is shown below. Example Live Demo import std.stdio; import std.random; void main() { int min = 1; int max = 10; immutable number = uniform(min, max + 1); // cannot modify immutable expression number // number = 34; typeof(number) value = 100; writeln(typeof(number).stringof, number); writeln(typeof(value).stringof, value); } When the above code is compiled and executed, it produces the following result − immutable(int)4 immutable(int)100 You can see in the above example how it is possible to transfer the data type to another variable and use stringof while printing. Const Variables in D Const variables cannot be modified similar to immutable. immutable variables can be passed to functions as their immutable parameters and hence it is recommended to use immutable over const. The same example used earlier is modified for const as shown below. Example Live Demo import std.stdio; import std.random; void main() { int min = 1; int max = 10; const number = uniform(min, max + 1); // cannot modify const expression number| // number = 34; typeof(number) value = 100; writeln(typeof(number).stringof, number); writeln(typeof(value).stringof, value); } If we compile and run above code, this would produce the following result − const(int)7 const(int)100 Immutable Parameters in D const erases the information about whether the original variable is mutable or immutable and hence using immutable makes it pass it other functions with the original type retained. A simple example is shown below. Example Live Demo import std.stdio; void print(immutable int[] array) { foreach (i, element; array) { writefln(“%s: %s”, i, element); } } void main() { immutable int[] array = [ 1, 2 ]; print(array); } When the above code is compiled and executed, it produces the following result − 0: 1 1: 2 Print Page Previous Next Advertisements ”;

D Programming – Inheritance

D Programming – Inheritance ”; Previous Next One of the most important concepts in object-oriented programming is inheritance. Inheritance allows to define a class in terms of another class, which makes it easier to create and maintain an application. This also provides an opportunity to reuse the code functionality and fast implementation time. When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class. The idea of inheritance implements the is a relationship. For example, mammal IS-A animal, dog IS-A mammal hence dog IS-A animal as well and so on. Base Classes and Derived Classes in D A class can be derived from more than one classes, which means it can inherit data and functions from multiple base classes. To define a derived class, we use a class derivation list to specify the base class(es). A class derivation list names one or more base classes and has the form − class derived-class: base-class Consider a base class Shape and its derived class Rectangle as follows − Live Demo import std.stdio; // Base class class Shape { public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height; } // Derived class class Rectangle: Shape { public: int getArea() { return (width * height); } } void main() { Rectangle Rect = new Rectangle(); Rect.setWidth(5); Rect.setHeight(7); // Print the area of the object. writeln(“Total area: “, Rect.getArea()); } When the above code is compiled and executed, it produces the following result − Total area: 35 Access Control and Inheritance A derived class can access all the non-private members of its base class. Thus base-class members that should not be accessible to the member functions of derived classes should be declared private in the base class. A derived class inherits all base class methods with the following exceptions − Constructors, destructors, and copy constructors of the base class. Overloaded operators of the base class. Multi Level Inheritance The inheritance can be of multiple levels and it is shown in the following example. Live Demo import std.stdio; // Base class class Shape { public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height; } // Derived class class Rectangle: Shape { public: int getArea() { return (width * height); } } class Square: Rectangle { this(int side) { this.setWidth(side); this.setHeight(side); } } void main() { Square square = new Square(13); // Print the area of the object. writeln(“Total area: “, square.getArea()); } When the above code is compiled and executed, it produces the following result − Total area: 169 Print Page Previous Next Advertisements ”;

D Programming – Arrays

D Programming – Arrays ”; Previous Next D programming language provides a data structure, named arrays, which stores a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data. It is often more useful to think of an array as a collection of variables of the same type. Instead of declaring individual variables, such as number0, number1, …, and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and …, numbers[99] to represent individual variables. A specific element in an array is accessed by an index. All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element. Declaring Arrays To declare an array in D programming language, the programmer specifies the type of the elements and the number of elements required by an array as follows − type arrayName [ arraySize ]; This is called a single-dimension array. The arraySize must be an integer constant greater than zero and type can be any valid D programming language data type. For example, to declare a 10-element array called balance of type double, use this statement − double balance[10]; Initializing Arrays You can initialize D programming language array elements either one by one or using a single statement as follows double balance[5] = [1000.0, 2.0, 3.4, 17.0, 50.0]; The number of values between square brackets[ ] on right side cannot be larger than the number of elements you declare for the array between square brackets [ ]. The following example assigns a single element of the array − If you omit the size of the array, an array just big enough to hold the initialization is created. Therefore, if you write double balance[] = [1000.0, 2.0, 3.4, 17.0, 50.0]; then you will create exactly the same array as you did in the previous example. balance[4] = 50.0; The above statement assigns element number 5th in the array a value of 50.0. Array with 4th index will be 5th, i.e., last element because all arrays have 0 as the index of their first element which is also called base index. The following pictorial representaion shows the same array we discussed above − Accessing Array Elements An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example − double salary = balance[9]; The above statement takes 10th element from the array and assigns the value to the variable salary. The following example implements declaration, assignment, and accessing arrays − Live Demo import std.stdio; void main() { int n[ 10 ]; // n is an array of 10 integers // initialize elements of array n to 0 for ( int i = 0; i < 10; i++ ) { n[ i ] = i + 100; // set element at location i to i + 100 } writeln(“Element t Value”); // output each array element”s value for ( int j = 0; j < 10; j++ ) { writeln(j,” t “,n[j]); } } When the above code is compiled and executed, it produces the following result − Element Value 0 100 1 101 2 102 3 103 4 104 5 105 6 106 7 107 8 108 9 109 Static Arrays Versus Dynamic Arrays If the length of an array is specified while writing program, that array is a static array. When the length can change during the execution of the program, that array is a dynamic array. Defining dynamic arrays is simpler than defining fixed-length arrays because omitting the length makes a dynamic array − int[] dynamicArray; Array Properties Here are the properties of arrays − Sr.No. Property & Description 1 .init Static array returns an array literal with each element of the literal being the .init property of the array element type. 2 .sizeof Static array returns the array length multiplied by the number of bytes per array element while dynamic arrays returns the size of the dynamic array reference, which is 8 in 32-bit builds and 16 on 64-bit builds. 3 .length Static array returns the number of elements in the array while dynamic arrays is used to get/set number of elements in the array. Length is of type size_t. 4 .ptr Returns a pointer to the first element of the array. 5 .dup Create a dynamic array of the same size and copy the contents of the array into it. 6 .idup Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. 7 .reverse Reverses in place the order of the elements in the array. Returns the array. 8 .sort Sorts in place the order of the elements in the array. Returns the array. Example The following example explains the various properties of an array − Live Demo import std.stdio; void main() { int n[ 5 ]; // n is an array of 5 integers // initialize elements of array n to 0 for ( int i = 0; i < 5; i++ ) { n[ i ] = i + 100; // set element at location i to i + 100 } writeln(“Initialized value:”,n.init); writeln(“Length: “,n.length); writeln(“Size of: “,n.sizeof); writeln(“Pointer:”,n.ptr); writeln(“Duplicate Array: “,n.dup); writeln(“iDuplicate Array: “,n.idup); n = n.reverse.dup; writeln(“Reversed Array: “,n); writeln(“Sorted Array: “,n.sort); } When the above code is compiled and executed, it produces the following result − Initialized value:[0, 0, 0, 0, 0] Length: 5 Size of: 20 Pointer:7FFF5A373920 Duplicate Array: [100, 101, 102, 103, 104] iDuplicate Array: [100, 101, 102, 103, 104] Reversed Array: [104, 103, 102, 101, 100] Sorted Array: [100, 101, 102, 103, 104] Multi Dimensional Arrays in D D programming allows multidimensional arrays. Here is the general form of a multidimensional array declaration − type name[size1][size2]…[sizeN]; Example The following declaration creates a three dimensional 5 . 10 . 4 integer array