The new, new phobos sneak preview

bearophile bearophileHUGS at lycos.com
Fri Apr 10 16:14:08 PDT 2009


Walter Bright:
> This C++0x article is relevant for comparison:
> http://www.reddit.com/r/programming/comments/8bijk/gcc_c0x_features_exploration/

"Advanced" features have to be used only if they improve the code. I don't like that little article and the following discussion.

The following D1 code shows two ways to solve that problem with my dlibs. The first code to try is the simplest, that is to scan the data three (or even four times):

double avg = cast(double)sum(data) / len(data);
putr("min, max, avg: ", min(data), " ", max(data), " ", avg);

It works with most kind of eager/lazy numerical data, for example a lazy generator that has no length. Note that sum() is sometimes faster than a simple loop.
In many situations that code (plus some safety against division by zero) is good enough.

If you know data is huge or you have found that code to be a bottleneck, and you want a single pass you can use something like the following (code written on the fly, no unittests present, it may contain bugs):
import d.templates: IsAA, BaseType1, Record;
import d.func: putr, min, max, sum, record, len;
import d.exceptions: EmptyException;


Record!(BaseType1!(TSeq), BaseType1!(TSeq), double) minMaxAvg1(TSeq)(TSeq seq, double start=0.0) {
    auto nitems = len(seq);
    if (!nitems)
        throw new EmptyException("minMaxAvg(): 'seq' can't be empty");
    return record(min(seq), max(seq), sum(seq, start) / nitems);
}


Record!(BaseType1!(TSeq), BaseType1!(TSeq), double) minMaxAvg2(TSeq)(TSeq seq, double start=0.0) {
    BaseType1!(TSeq) dmin, dmax;
    double dtot = start;
    int nitems;

    static if (IsAA!(TSeq)) {
        foreach (el, _; seq) {
            if (nitems == 0) {
                dmin = el;
                dmax = el;
            }
            if (dmin > el) dmin = el;
            if (dmax < el) dmax = el;
            dtot += el;
            nitems++;
        }
    } else {
        foreach (el; seq) {
            if (nitems == 0) {
                dmin = el;
                dmax = el;
            }
            if (dmin > el) dmin = el;
            if (dmax < el) dmax = el;
            dtot += el;
            nitems++;
        }
    }
    if (!nitems)
        throw new EmptyException("minMaxAvg(): 'seq' can't be empty");
    return record(dmin, dmax, dtot / nitems);
}

void main() {
    int[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    putr("<min, max, avg>: ", minMaxAvg1(data));
    putr("<min, max, avg>: ", minMaxAvg2(data));
}

(Notice the ugly code duplication caused by the AAs).

The output:
min, max, avg: 1 10 5.5
<min, max, avg>: record(1, 10, 5.5)

Bye,
bearophile



More information about the Digitalmars-d mailing list