www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - To use opDispatch

reply bearophile <bearophileHUGS lycos.com> writes:
I have seen this bug report:
http://d.puremagic.com/issues/show_bug.cgi?id=4224

Do you know any way to make the following code work? It can be useful,
especially once the int type can be replaced with a good variant type:

struct A {
    int[string] table;

    int opDispatch(string s)() {
        return table[s];
    }

    void opDispatch(string s)(int x) {
        table[s] = x;
    }
}

void main() {
    A a;
    a.i = 10;
    assert(a.i == 10);
}


After about thirty attempts I have seen that this works, but it's bad:

struct A(T) {
    T[string] table;

    T opDispatch(string s)(T x=T.min) {
        if (x != T.min)
            table[s] = x;
        return table[s];
    }
}

void main() {
    A!int a;
    a.i = 10;
    assert(a.i == 10);
}

Bye,
bearophile
May 23 2010
next sibling parent reply BCS <none anon.com> writes:
Hello bearophile,

 I have seen this bug report:
 http://d.puremagic.com/issues/show_bug.cgi?id=4224
 Do you know any way to make the following code work? It can be useful,
 especially once the int type can be replaced with a good variant type:
 
 struct A {
 int[string] table;
 int opDispatch(string s)() {
 return table[s];
 }
 void opDispatch(string s)(int x) {
 table[s] = x;
 }
 }
 void main() {
 A a;
 a.i = 10;
 assert(a.i == 10);
 }
IIRC I got more or less what you want somewhere in here: http://dsource.org/projects/scrapple/browser/trunk/units/si2.d I'll see if I can chop it down a bit. -- ... <IXOYE><
May 23 2010
parent reply BCS <none anon.com> writes:
Hello BCS,

 Hello bearophile,
 
 I have seen this bug report:
 http://d.puremagic.com/issues/show_bug.cgi?id=4224
 Do you know any way to make the following code work? It can be
 useful,
 especially once the int type can be replaced with a good variant
 type:
 struct A {
 int[string] table;
 int opDispatch(string s)() {
 return table[s];
 }
 void opDispatch(string s)(int x) {
 table[s] = x;
 }
 }
 void main() {
 A a;
 a.i = 10;
 assert(a.i == 10);
 }
IIRC I got more or less what you want somewhere in here: http://dsource.org/projects/scrapple/browser/trunk/units/si2.d I'll see if I can chop it down a bit.
I guess I didn't rememeber correctly. Anyway, this work: import std.stdio; template If(bool b, T, F) { static if(b) alias T If; else alias F If; } struct S { int[string] vals; template opDispatch(string s) { If!(T.length == 1, void, int) opDispatch(T...)(T t) { static if(T.length == 1) vals[s] = t[0]; else return vals[s]; } } } void main() { S s; s.foo = 5; writef("%s\n", s.foo()); } -- ... <IXOYE><
May 23 2010
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
BCS:

 I guess I didn't rememeber correctly. Anyway, this work:
 
 
 import std.stdio;
 
 template If(bool b, T, F) { static if(b) alias T If; else alias F If; }
 
 struct S
 {
    int[string] vals;
    template opDispatch(string s)
    {
    If!(T.length == 1, void, int) opDispatch(T...)(T t)
    {
       static if(T.length == 1) vals[s] = t[0];
       else return vals[s];
    }
    }
 }
 
 void main()
 {
   S s;
   s.foo = 5;
   writef("%s\n", s.foo());
 }
It works :-) In my alternative implementations I have never put that () after the new method name. Using property here doesn't work. I have modified (hopefully improved) your version like this: import std.stdio: writeln; import std.traits: isImplicitlyConvertible; struct S(T) { T[string] data; template opDispatch(string name) { property T opDispatch(Types...)(Types args) if (!args.length || (args.length == 1 && isImplicitlyConvertible!(Types[0],T))) { static if (args.length) { data[name] = args[0]; return args[0]; } else return data[name]; } } } void main() { S!long s; s.foo = 5; // writeln(s.foo); // err writeln(s.foo()); } Bye, bearophile
May 23 2010
parent bearophile <bearophileHUGS lycos.com> writes:
bearophile:
 Using  property here doesn't work.
Of course it doesn't work, it doesn't get applied to the strings magically. The compiler can implement this syntax sugar, eventually. Bye, bearophile
May 23 2010
prev sibling parent reply Pelle <pelle.mansson gmail.com> writes:
On 05/23/2010 09:17 PM, BCS wrote:
 template If(bool b, T, F) { static if(b) alias T If; else alias F If; }
That's in phobos, :) http://digitalmars.com/d/2.0/phobos/std_traits.html#Select
May 24 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Pelle:
 That's in phobos, :)
 
 http://digitalmars.com/d/2.0/phobos/std_traits.html#Select
Right. I think a name like IF or If can be OK, I have called it If. Bye, bearophile
May 24 2010
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
bearophile <bearophileHUGS lycos.com> wrote:

 I have seen this bug report:
 http://d.puremagic.com/issues/show_bug.cgi?id=4224

 Do you know any way to make the following code work? It can be useful,
 especially once the int type can be replaced with a good variant type:
struct A { int[string] table; auto opDispatch( string name, T... )( T args ) { static if ( T.length == 0 ) { return table[s]; } else if ( T.length == 1 ) { table[ name ] = args[0]; } else { static assert( false, "Wrong parameter count to opDispatch" ); } } } You could factor out the static ifs to template constraints, if you wish. -- Simen
May 23 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:

 struct A {
    int[string] table;
 
    auto opDispatch( string name, T... )( T args ) {
      static if ( T.length == 0 ) {
        return table[s];
      } else if ( T.length == 1 ) {
        table[ name ] = args[0];
      } else {
        static assert( false, "Wrong parameter count to opDispatch" );
      }
    }
 }
But have you tried to run it? That is similar to one of my first versions, and it doesn't work, I don't know why. This is your code, you can try to run it if you want: import std.stdio: writeln; struct A { int[string] table; auto opDispatch(string name, T...)(T args) { static if (T.length == 0) { return table[name]; } else if (T.length == 1) { table[name] = args[0]; } else { static assert(false, "Wrong parameter count to opDispatch"); } } } void main() { A a; a.foo = 5; writeln(a.foo); } Bye and thank you, bearophile
May 23 2010
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
bearophile <bearophileHUGS lycos.com> wrote:

 But have you tried to run it? That is similar to one of my first  
 versions, and it doesn't work, I don't know why.
You're right. Property syntax is what causes it. It only instantiates the template with the parameter for the name.[1] This code seems to work correctly: struct bar { int[string] table; template opDispatch( string name ) { property auto opDispatch( T... )( T args ) { static if (T.length == 0) { return table[name]; } else static if (T.length == 1) { table[name] = args[0]; } else { pragma( msg, to!string( T.length ) ); static assert(false, "Wrong parameter count to opDispatch"); } } } } void main( ) { bar b; b.foz = 34; writeln( b.foz( ) ); } Note however, that property syntax does not work for the degenerate case of 0 arguments, i.e. the getter. One has to call it without the benefit of property syntax. [1]: http://d.puremagic.com/issues/show_bug.cgi?id=620 -- Simen
May 23 2010