On Apr 30, 11 03:12, Andrei Alexandrescu wrote:
On 4/29/11 8:50 AM, Denis Koroskin wrote:
On Thu, 28 Apr 2011 03:10:15 +0400, Andrej Mitrovic
<andrej.mitrov...@gmail.com> wrote:

I often see code written like this:

if (value == somevalue ||
value == someothervalue ||
value == yetanothervalue);

You could use the switch statement. But that introduces indentation,
and is rarely used for a couple of values.

I really like the "in" keyword, and I also like hashes since they can
potentially speed up look-ups compared to conventional arrays. So I
thought it would be cool to have a Hash template that constructs an
associative array which you can use especially in if statements when
you just want to know if a runtime value matches some predetermined
value.

Here's my attempt at writing it:
http://codepad.org/c4sYDSyR

Whaddya think?

Try this:
[snip]

Nice work. I think this code could earn a place in Phobos:

auto either(Keys...)(Keys keys)
{
static struct Result
{
bool opIn_r(Key)(Key key)
{
foreach (k; keys) {
if (k == key) {
return true;
}
}
return false;
}
private Keys keys;
}
return Result(keys);
}


Andrei


This is generally 2~3 times slower than a compile-time solution if the keys are known in advance (and the former is 1~2 times slower than using x == y || x == z || ... directly)

(Why do you still use opIn_r? ;) )


import std.datetime, std.algorithm, std.typecons, std.stdio;

auto either(Keys...)(Keys keys)
{
    static struct Result
    {
        bool opIn_r(Key)(Key key)
        {
            foreach (k; keys) {
                if (k == key) {
                    return true;
                }
            }
            return false;
        }
        private Keys keys;
    }
    return Result(keys);
} 

struct ctEither(keys...) {
    @safe bool opBinaryRight(string op:"in", T)(in T x) const pure nothrow {
        foreach (k; keys)
            if (x == k)
                return true;
        return false;
    }
}

struct ctEither2(keys...) {
    @safe bool opBinaryRight(string op:"in", T)(in T x) const pure nothrow {
        switch (x) {
            default:
                return false;
            foreach (k; keys) {
                case k:
                    return true;
            }
        }
        return false;
    }
}

__gshared int p = 1234567890;

void a() {
    assert(p !in ctEither!(1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 
123456789)() );
}
void b() {
    assert(p !in either(1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 
123456789));
}
void c() {
    assert(![1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 
123456789].canFind(p));
}
void d() {
    assert(!(p == 1 || p == 12 || p == 123 || p == 1234 || p == 12345 || p == 
123456 || p == 1234567 || p == 12345678 || p == 123456789));
}
void e() {
    assert(p !in ctEither2!(1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 
123456789)() );
}
void main() {
    writeln( benchmark!c(1_000_000)[0].to!("msecs", int) );
     
    writeln( benchmark!a(1_000_000)[0].to!("msecs", int) );
    writeln( benchmark!b(1_000_000)[0].to!("msecs", int) );
    writeln( benchmark!d(1_000_000)[0].to!("msecs", int) );
    writeln( benchmark!e(1_000_000)[0].to!("msecs", int) );
}

Reply via email to