goto

Daniel Keep daniel.keep.lists at gmail.com
Thu Feb 5 22:37:17 PST 2009



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



More information about the Digitalmars-d mailing list