Who here actually uses D?

Adam D. Ruppe destructionator at gmail.com
Sat Jan 1 17:05:27 PST 2011


Robert Clipsham wrote:
> I hit the exact same issue recently but in D1 - seems templated
> methods don't like being overloaded.

Yeah. Usually it's not a big deal, since you can just handle
it inside the template very easily (often moreso than a traditional
overload even, thanks to static if) but there's times when that
can't work either.

> In this situation couldn't you use
> opDispatch(T:string)(T) and opDispatch(T:int)(T)?
> I'd guess not, but I don't know how opDispatch works, or what
> your code looks like!

That, specifically, won't work for opDispatch because it needs
to have at least a string argument:

===
struct A {
    void opDispatch(string field)(string argument = null) {
           writeln(field, "=", argument);
    }
}

void main() {
    A a;

    a.field1; // calls a.opDispatch!("field1")();
    a.field2 = "whoa"; // yay property. a.opDispatch!("field2")("whoa");
}
===

Cool. But, what if you want to do a.field = 10;? That is, pass
an int instead of a string?

Now, it will work if you do:

===
    string opDispatch(string field, T)(T t) {
            // blah blah
    }

    A a;
    a.field1(10);
    a.field1("hello");
===

And you can specialize T however you want. But, take that same
code and write

auto whatever = a.field1;
a.field1 = "hello";
a.field2 = 10;

And things start to break down. The getter doesn't work because
it doesn't match the template definition. The setters I believe
do work here though. (I'm not compiling as I go, so I might be
forgetting something)

So you want the getter to work. Before it worked due to a
default argument. What if we overload the template for zero
arguments or one argument?

string opDispatch(string field)() {} // getter
string opDispatch(string field, T)(T t) {} // setter


At this point, you'd expect it all to work. The getter compiles...
but the setter then fails because it "matches multiple template
definitions". Uh, no it doesn't, but the compiler apparently
looked at the property, rewrote the first part to opDispatch,
and then gave up before getting into the actual arguments being
passed in.

(My actual code used T... because I'd like to be able to handle:

val = a.field;
a.field = val;
a.field(val);
a.field(val, arg2);

all with one class. But I'm pretty sure the plain T argument
did the same thing.

Of those, each is easily solved on its own. #2 and #3 don't play
well together since once the property sugar is stripped off,
they are the same. If we could overload @property and regular
function, it would work, but that doesn't work today.

#2 and #4 and #1 and #4 don't play well together as explained
above.

So for today's little project, since each one works individually,
I just broke them down into separate functions and helper objects.
It no longer mimics Javascript as exactly as I'd like here, but
it does work.

I've previously tried to do all this with a dmdscript port too.
There, the problem I hit was templating opDispatch with a
recursive object:

MyObject obj;
MyObject obj2 = obj.field; // works
obj.field = "hello"; // works
obj2.field2; // works
obj2.field2 = obj.field; // works

obj.field.field2; // works
obj.field.field2 = "hello"; // fails, despite the fact we saw each
     //part working independently above. It complains about
     // the returned type not matching or something weird; I tried
     // this months ago and don't remember all the specifics.
)



But, oh well, I can live without the combination anyway. It's
more of a novelty than anything else to me anyway. (It'll be cool
to say "yeah we can basically write full javascript from inside
D" some day, but I doubt I'd actually put it to serious use.)


More information about the Digitalmars-d mailing list