Mixin replacement for switch...case?

Philippe Sigaud philippe.sigaud at gmail.com
Tue Oct 23 12:48:05 PDT 2012


> The solution (not variadic though) would be:
>
> mixin template Select!(alias value,
>   alias if0, alias then0,
>   alias if1, alias then1,
>   alias if2, alias then2,
>   alias thenDefault)
>
> {
>   switch(value) {
>     case if0 : { then0(); } break;
>     case if1 : { then1(); } break;
>     case if2 : { then2(); } break;
>     default : thenDefault();
>   }
> }

You can get something interesting a few lines of code:

template select(cases...) if (cases.length % 2 == 1)
{
    auto select(Input)(Input input)
    {
        static if (cases.length == 1) // Default case
            return cases[0]();
        else // standard case
        {
            if (input == cases[0])
                return cases[1]();
            else
                return .select!(cases[2..$])(input);
        }
    }
}


void main()
{
    // With block delegates
    alias select!(0, { writeln("Zero.");},
                  1, { writeln("One."); },
                     { writeln("Something else.");}) counter;

    counter(0);
    counter(1);
    counter(10_000);

    // With anonymous functions:
    alias select!(0, ()=> "Zero.",
                  1, ()=> "One.",
                     ()=> "Something else.") counter2;

    writeln(counter2(0));
    writeln(counter2(1));
    writeln(counter2(10_000));
}

A slightly more generic version takes predicates as first arguments,
as Lisp's cond form:

template cond(cases...) if (cases.length % 2 == 1)
{
    auto cond(Input)(Input input)
    {
        static if (cases.length == 1) // Default case
            return cases[0]();
        else // standard case
        {
            if (cases[0](input)) // The only difference with select
                return cases[1]();
            else
                return .cond!(cases[2..$])(input);
        }
    }
}

void main()
{
    alias cond!((a) => a < 0, ()=> "Negative.",
                (a) => a > 0, ()=> "Positive.",
                              ()=> "Zero.") counter3;

    writeln(counter3(-10));
    writeln(counter3(1));
    writeln(counter3(0));
}




Philippe


More information about the Digitalmars-d mailing list