Book Image

D Cookbook

By : Adam Ruppe
Book Image

D Cookbook

By: Adam Ruppe

Overview of this book

Table of Contents (21 chapters)
D Cookbook
Credits
Foreword
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

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:

  1. Declare an array variable by using the following statement:

    int[] arr;
  2. Append data to it as shown:

    arr ~= 1;
    arr ~= [2, 3];
  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;
    }
  4. 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[] or arr[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.