goto

bearophile bearophileHUGS at lycos.com
Fri Feb 6 04:16:29 PST 2009


Daniel Keep:

> Of course, if we had foreach support for tuple unpacking...
> 
> double euclideanDistance(Range)(Range as, Range bs, double limit)
> {
>     limit *= limit;
>     double result = 0;
>     foreach( a, b ; zip(as, bs, ZipStyle.EnforceLength) )
>     {
>         auto t = a.head - b.head;
>         result += t * t;
>         if (result >= limit) break;
>     }
>     return sqrt(result);
> }

That's closer to the way code is meant to be written :-)

Few other details:
auto t = a.head - b.head;
result += t * t;
May become:
result += (a.head - b.head) ** 2;

This isn's nice looking (you also may want to zip many iterables):
zip(as, bs, ZipStyle.EnforceLength)

How many zip behaviours are useful? Among the possible ones there are:
1) stop as soon as the shorter iterable ends;
2) stop when the longest iterable ends, yielding item.init items to fill blanks.
3) assert that they are all of the same length, as you ask for.

A simpler solution is to make zip support only (1), avoid ugly constants.

To support (2) you it can be invented an iterable wrapper that yields the constant you want when the given iterable ends, for example:
xzip(iter1, xextend(iter2, 0.0))

And regarding (3) I don't have many ideas.

But why the original code by Alex has those enforce() to be sure the iterables have the same length? Maybe the best thing is just to not enforce that. So this may be a readable version (no .heads):

double limitedEuclideanDistance(Range)(Range iter2, Range iter2, double limit) {
    limit = limit ** 2;
    double sqr_dist = 0.0;
    foreach (x1, x2 in xzip(iter1, iter2)) {
        sqr_dist += (x1 - x2) ** 2;
        if (sqr_dist >= limit)
            break;
    }
    return sqrt(sqr_dist);
}

Bye,
bearophile



More information about the Digitalmars-d mailing list