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