Building and processing arrays
D has three types of arrays built in: static arrays, with a set length known at compile time; dynamic arrays, with a variable length; and associative arrays, which are similar to hashmaps or dictionaries in other languages. D's arrays and array slices are a very flexible and easy-to-use tool used in almost all D programs. Here, you'll look at some of their capabilities by building a list of integers and then finding the sum of the contents.
How to do it…
Let's use the following steps to build and process arrays:
Declare an array variable by using the following statement:
int[] arr;
Append data to it as shown:
arr ~= 1; arr ~= [2, 3];
Create a function that takes a slice and does some processing on it, as shown in the following code:
int sum(in int[] data) { int total = 0; foreach(item; data) total += item; return total; }
Pass a slice of the array to the function, as shown in the following code:
// Dynamic arrays can be passed directly. Static // arrays can be sliced with the [] operator.. writeln("The sum of ", arr, " is ", sum(arr));
How it works…
D types are always read from right to left. The int[]
array is an array of integers. The string*[]*
pointer is a pointer to an array of pointers to string. The int[][]
array is an array of an array of integers; a staggered array.
There are two kinds of arrays in D: static and dynamic. A static array is a value type that represents a solid, fixed-size block of memory (this corresponds to an array in C). A dynamic array is conceptually a struct with two members: a pointer to the data and the length of the data. Thus, unlike a static array, dynamic arrays and slices have reference semantics. You can access the pointer and length components with the .ptr
and .length
properties, respectively. In the example here, you used a dynamic array, which has the same syntax as a slice.
There are three major operations on an array: appending, indexing, and slicing.
Appending: This is done with the
~=
operator. There's also the binary~
operator (not to be confused with the unary~
operator, which inverts bits), which concatenates two arrays to form a new one. You can append an individual element or another static or dynamic array of compatible type.Indexing: This is done with the
[expr]
operator, for example,arr[0]
. This is very similar to C, but a key difference in D is that arrays know their own length, enabling automatic bounds checking. If you attempt to access an out-of-bounds index, you will see a RangeError.Slicing: This is done with the
[]
operator, for example,arr[]
orarr[0 .. 2]
. This is done to get a view into an array starting at the left-hand index (inclusive) and ending at the right-hand index (exclusive, which means you can use the array's length as an ending bound, which also has a shorthand syntax$
).[][][]
gets a slice into the whole thing, and it is useful to pass static arrays or user-defined array types to functions expecting slices or dynamic arrays. Slicing is a fast, constant-time operation.
You can iterate over an array or slice using the foreach
loop. You put the iteration variable, then a semicolon, and then the variable you want to iterate over. You do not have to explicitly name the variable's type, for example, foreach(item; array)
or foreach(int item; array)
.
In the example code, the function parameter is defined as an in
variable. The in
variable is shorthand keyword to give the parameter the storage classes of const
and scope
. What this means in practice is that you must not modify the array or its contents (this will be a compile error), nor should you keep a copy of or return a reference to the passed array.
There's more…
D also supports array vector operations like the following:
arr[] = arr[] + 5;;;
This code will add five to every element of the array. You can also create array copies this way: arr2[] = arr[]
. This will copy arr
into arr2
. For this to work, the lengths of the two arrays must already match. To do an array copy without matching lengths, you can write array.dup
.
See also
http://dlang.org/d-array-article.html for details of array memory management and the difference between a dynamic array and a slice.
http://dlang.org/arrays.html for a more complete listing of what D's arrays can do.
The Creating an array replacement recipe in Chapter 5, Resource Management. This will show you how to create a new array type that has the same capabilities as the built-in arrays, with custom behavior or memory allocation strategies.
The Avoiding the garbage collector recipe in Chapter 5, Resource Management. This will discuss the built-in array's memory allocation habits and what to avoid if you don't want to use the garbage collector.