Associative Arrays

Associative arrays are used to represent collections of data elements that can be retrieved by specifying a name called a key. D associative array keys are formed by a list of scalar expression values called a tuple. You can think of the array tuple itself as an imaginary parameter list to a function that is called to retrieve the corresponding array value when you reference the array. Each D associative array has a fixed key signature consisting of a fixed number of tuple elements where each element has a given, fixed type. You can define different key signatures for each array in your D program.

Associative arrays differ from normal, fixed-size arrays in that they have no predefined limit on the number of elements, the elements can be indexed by any tuple as opposed to just using integers as keys, and the elements are not stored in preallocated consecutive storage locations. Associative arrays are useful in situations where you would use a hash table or other simple dictionary data structure in a C, C++, or Java™ language program. Associative arrays give you the ability to create a dynamic history of events and state captured in your D program that you can use to create more complex control flows.

To define an associative array, you write an assignment expression of the form:

name [ key ] = expression ;

where name is any valid D identifier and key is a comma-separated list of one or more expressions. For example, the following statement defines an associative array a with key signature [ int, string ] and stores the integer value 456 in a location named by the tuple [ 123, "hello" ]:

a[123, "hello"] = 456;

The type of each object contained in the array is also fixed for all elements in a given array. Because a was first assigned using the integer 456, every subsequent value stored in the array will also be of type int. You can use any of the assignment operators defined in Chapter 2 to modify associative array elements, subject to the operand rules defined for each operator. The D compiler will produce an appropriate error message if you attempt an incompatible assignment. You can use any type with an associative array key or value that you can use with a scalar variable. You cannot nest an associative array within another associative array as a key or value.

You can reference an associative array using any tuple that is compatible with the array key signature. The rules for tuple compatibility are similar to those for function calls and variable assignments: the tuple must be of the same length and each type in the list of actual parameters must be compatible with the corresponding type in the formal key signature. For example, if an associative array x is defined as follows:

x[123ull] = 0;

then the key signature is of type unsigned long long and the values are of type int. This array can also be referenced using the expression x['a'] because the tuple consisting of the character constant 'a' of type int and length one is compatible with the key signature unsigned long long according to the arithmetic conversion rules described in Type Conversions.

If you need to explicitly declare a D associative array before using it, you can create a declaration of the array name and key signature outside of the probe clauses in your program source code:

int x[unsigned long long, char];

BEGIN
{
	x[123ull, 'a'] = 456;
}

Once an associative array is defined, references to any tuple of a compatible key signature are permitted, even if the tuple in question has not been previously assigned. Accessing an unassigned associative array element is defined to return a zero-filled object. A consequence of this definition is that underlying storage is not allocated for an associative array element until a non-zero value is assigned to that element. Conversely, assigning an associative array element to zero causes DTrace to deallocate the underlying storage. This behavior is important because the dynamic variable space out of which associative array elements are allocated is finite; if it is exhausted when an allocation is attempted, the allocation will fail and an error message will be generated indicating a dynamic variable drop. Always assign zero to associative array elements that are no longer in use. See Chapter 16, Options and Tunables for other techniques to eliminate dynamic variable drops.