Andrei Alexandrescu wrote: > I was coding a simple Euclidean distance function with limit: > > double euclideanDistance(Range)(Range a, Range b, double limit) > { > limit *= limit; > double result = 0; > for (; !a.empty; a.next, b.next) > { > enforce(!b.empty); > auto t = a.head - b.head; > result += t * t; > if (result >= limit) goto thatsit; > } > enforce(b.empty); > thatsit: > return sqrt(result); > } > > How would an elegant goto-less approach look like? It should not > duplicate code, e.g. the call to sqrt. > > > Andrei
The goto approach looks a bit messy because it isn't immediately clear what the relationship between a and b's lengths are. Personally, I'd do it like this: double euclideanDistance(Range)(Range as, Range bs, double limit) { limit *= limit; double result = 0; foreach( ab ; zip(as, bs, ZipStyle.EnforceLength) ) { auto t = ab._0.head - ab._1.head; result += t * t; if (result >= limit) break; } return sqrt(result); } 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); } :D -- Daniel