Slices in D Programming Language

import std.stdio;
import std.algorithm;

void main() {
    // Unlike arrays, dynamic arrays in D are typed only by the
    // elements they contain (not the number of elements).
    // An uninitialized dynamic array is empty and has length 0.
    string[] s;
    writeln("uninit:", s, s == null, s.length == 0);

    // To create an empty dynamic array with non-zero length, use
    // the new operator. Here we create a dynamic array of
    // strings of length 3 (initially null-valued).
    s = new string[3];
    writefln("emp: %s len: %d cap: %d", s, s.length, s.capacity);

    // We can set and get just like with arrays.
    s[0] = "a";
    s[1] = "b";
    s[2] = "c";
    writeln("set:", s);
    writeln("get:", s[2]);

    // length returns the length of the dynamic array as expected.
    writeln("len:", s.length);

    // In addition to these basic operations, dynamic arrays
    // support several more that make them richer than
    // fixed-length arrays. One is the ~ operator for concatenation,
    // which returns a new dynamic array.
    s ~= "d";
    s ~= ["e", "f"];
    writeln("apd:", s);

    // Dynamic arrays can also be copied using the dup property.
    // Here we create a new dynamic array c with the same contents as s.
    auto c = s.dup;
    writeln("cpy:", c);

    // Dynamic arrays support a "slice" operator with the syntax
    // array[low..high]. For example, this gets a slice of the
    // elements s[2], s[3], and s[4].
    auto l = s[2..5];
    writeln("sl1:", l);

    // This slices up to (but excluding) s[5].
    l = s[0..5];
    writeln("sl2:", l);

    // And this slices up from (and including) s[2].
    l = s[2..$];
    writeln("sl3:", l);

    // We can declare and initialize a variable for a dynamic array
    // in a single line as well.
    auto t = ["g", "h", "i"];
    writeln("dcl:", t);

    // D's standard library contains a number of useful
    // utility functions for arrays.
    auto t2 = ["g", "h", "i"];
    if (equal(t, t2)) {
        writeln("t == t2");
    }

    // Dynamic arrays can be composed into multi-dimensional data
    // structures. The length of the inner arrays can vary, unlike
    // with multi-dimensional static arrays.
    int[][] twoD;
    twoD.length = 3;
    for (int i = 0; i < 3; i++) {
        int innerLen = i + 1;
        twoD[i].length = innerLen;
        for (int j = 0; j < innerLen; j++) {
            twoD[i][j] = i + j;
        }
    }
    writeln("2d: ", twoD);
}

Note that while dynamic arrays in D are different types than fixed-length arrays, they are rendered similarly by writeln.

To run this program, save it as slices.d and use the D compiler:

$ dmd -run slices.d
uninit:[] false true
emp: [null, null, null] len: 3 cap: 3
set:["a", "b", "c"]
get:c
len:3
apd:["a", "b", "c", "d", "e", "f"]
cpy:["a", "b", "c", "d", "e", "f"]
sl1:["c", "d", "e"]
sl2:["a", "b", "c", "d", "e"]
sl3:["c", "d", "e", "f"]
dcl:["g", "h", "i"]
t == t2
2d: [[0], [1, 2], [2, 3, 4]]

D’s dynamic arrays are similar to Go’s slices in many ways, providing a flexible and powerful interface to sequences. They can grow and shrink dynamically, and support operations like slicing and concatenation.

Now that we’ve seen arrays and dynamic arrays, we’ll look at D’s other key builtin data structure: associative arrays (similar to Go’s maps).