Listings Schadek, D

Listing 1: Einfache average-Funktion mit Test
double average(int[] arr) @safe {
    import std.array : empty;

    if(arr.empty) {
        return double.init;
    }

    int sum;
    foreach(int it; arr) {
        sum += it;
    }
    return sum / cast(double)arr.length;
}

@safe unittest {
    import std.math : approxEqual, isNaN;

    assert(approxEqual(average([1, 2]), 1.5));
    assert(approxEqual(average([1, 2, 3]), 2.0));
    assert(isNaN(average([])));

    enum ctAvg = average([1,2]);
}

--------

Listing 2: Arraybeispiele
unittest {
    int[] arr = [1,2,3];
    assert(arr.length == 3);

    int[] copy = arr[1 .. 3];
    copy[0] = 1337;
    assert(arr[1] == 1337);

    int[3] staticArray = [2, 2674, 6];

    arr[] *= 2;
    assert(staticArray[] == arr);

    int[] two = new int[3];
    two = arr;
    two = two ~ staticArray;
    assert(two == [2, 2674, 6, 2, 2674, 6]);
}

--------

Listing 3: Benutzung von Ranges
import std.array : empty;

unittest {
    import std.algorithm : filter, map, splitter;
    import std.stdio : writefln, File;
    import std.string : stripRight;

    double avg = File("listing3.d")
        .byLine
        .map!(line => line.stripRight)
         .filter!(line => !line.empty)
         .map!(line => line.length)
         .average;

    writefln!("The average non empty line length is %.4f")(avg);
}

double average(R)(R range) {
    if(range.empty) {
        return double.init;
    }

    int sum;
    int cnt;
    foreach(it; range) {
        sum += it;
        ++cnt;
    }
    return sum / cast(double)cnt;
}
// Funktion testen
unittest {    // Zweiter Unit-Test
    import std.math : approxEqual;

    double avg1 = average!(int[])([1, 2]);
    double avg2 = average([1, 2]);
    assert(approxEqual(avg1, avg2));
}

--------

Listing 4: Komplexe average-Funktion mit Template-Constraint
import std.range : isInputRange;
import std.array : empty;

double average(R)(R range) if(isInputRange!R) {
    enum hasLength = __traits(hasMember, R, "length");

    if(range.empty) {
        return double.init;
    }

    int sum;

    static if(hasLength) {
        immutable cnt = range.length;
    } else {
        size_t cnt;
    }

    foreach(it; range) {
        sum += it;

        static if(!hasLength) {
            ++cnt;
        }
    }
    return sum / cast(double)cnt;
}

unittest {
    static assert(!__traits(compiles, average(1)));
    static assert( __traits(compiles, average([1,2])));
}

--------

Listing 5: Finale average-Funktion
import std.range : isInputRange, ElementType;
import std.traits : isFloatingPoint, isIntegral;
import std.array : empty;

double average(R)(R range) if(isInputRange!R) {
    alias ET = ElementType!R;

    static if(isFloatingPoint!ET) {
        alias SumType = double;
    } else static if(isIntegral!ET) {
        alias SumType = long;
    } else {
        static assert(false, R.stringof);
    }

    if(range.empty) {
        return double.init;
    }

    SumType sum = 0;

    enum hasLength = __traits(hasMember, R, "length");

    static if(hasLength) {
        immutable cnt = range.length;
    } else {
        size_t cnt;
    }

    foreach(it; range) {
        sum += it;
        static if(!hasLength) {
            ++cnt;
        }
    }
    return sum / cast(double)cnt;
}

--------

Listing 6: Interoperabilität von C, C++ und D
extern(C) int add2inC(int);
extern(C++) int add3inCpp(int);

extern(C) int calledFromC(int a) {
    return a + 5;
}

int main() {
    int a = add2inC(1);
    assert(a == 8);

    int b = add3inCpp(2);
    assert(b == 5);
    return a + b;
}

--------

Listing 7: In C geschriebene Funktionen
int calledFromC(int); 

int add2inC(int a) {
    return calledFromC(a + 2);
}

--------

Listing 8: Funktionen in C++
int add3inCpp(int a) {
    return a + 3;
}

--------

Listing 9: String Mixins zur Kompilierzeit
string printGen() {
    return `import std.stdio;
        writeln("Hello World");`;
}

void main() {
    mixin(printGen());
}

