On Tue, 01 Dec 2009 19:02:27 +0300, Steven Schveighoffer
<schvei...@yahoo.com> wrote:
On Tue, 01 Dec 2009 10:25:43 -0500, Denis Koroskin <2kor...@gmail.com>
wrote:
On Tue, 01 Dec 2009 17:12:38 +0300, Steven Schveighoffer
<schvei...@yahoo.com> wrote:
On Tue, 01 Dec 2009 08:49:58 -0500, Denis Koroskin <2kor...@gmail.com>
wrote:
On Tue, 01 Dec 2009 16:46:25 +0300, Steven Schveighoffer
<schvei...@yahoo.com> wrote:
On Mon, 30 Nov 2009 23:32:21 -0500, Bill Baxter <wbax...@gmail.com>
wrote:
On Mon, Nov 30, 2009 at 7:12 PM, Walter Bright
<newshou...@digitalmars.com> wrote:
Bill Baxter wrote:
So we can overload on @property-ness?
No.
I.e. this works
struct S
{
@property
float x() { return 1.0f; }
float x() { return 2.0f; }
}
void main()
{
S s;
writefln("%s", s.x); // writes 1.0
writefln("%s", s.x()); // writes 2.0
}
That just looks wrong.
Ok, so you can't have both dynamic properties and dynamic methods
with
this. One or the other, your pick.
Seems like an unfortunate limitation.
what a minute, can't you use template conditionals to distinguish?
i.e. I would expect this to work:
struct S
{
@property float opDispatch(string s)() if (s == "x") {return
1.0f;}
float opDispatch(string s)() { return 2.0f;}
}
void main()
{
S s;
writefln("%s", s.x); // 1.0
writefln("%s", s.y()); // 2.0
}
Overloading opDispatch based on the called symbol name should always
be possible, and overloading on parameter types is always possible.
-Steve
What if you don't know argument names a-priori? Consider a generic
Dynamic class that has nothing but a single opDispatch method.
although opDispatch allows some dynamic function definitions, the
*usage* of opDispatch is always static. The question is, if you are
for example wrapping another type, can you introspect the attributes
of its methods?
For example, I'd expect something like this should be possible in the
future:
struct Wrapper(T)
{
T t;
@property auto opDispatch(string s)() if(isProperty!T(s) )
{mixin("return t." ~ s ~ ";");} // getters
@property auto opDispatch(string s, A)(A arg) if(isProperty!T(s) )
{mixin("return (t." ~ s ~ " = arg);"); } // setters
auto opDispatch(string s, A...)(A args) { mixin("return t." ~ s ~
"(args);");}
}
Now, given the function attributes that are possible (this does not
include const and immutable, which are overloaded via parameter
types), this is going to get pretty ugly quickly. Unfortunately, the
attributes are not decided by the caller, but by the callee, so you
have to use template conditionals. It would be nice if there was a
way to say "copy the attributes from function x" when defining
template functions in a way that doesn't involve conditionals, but
even then, you would have a hard time defining such usage because you
don't know what function you want until you evaluate the template
string.
-Steve
I might work with your design, but it will lead to considerable code
bloat, and it's not that static after all.
I'd say that you could achieve the same with method forwarding using
alias this:
struct Wrapper(T)
{
T t;
alias this t;
}
The true power of opDispatch comes with a fully Dynamic type, that has
no type information until runtime:
void foo(Dynamic duck)
{
duck.quack():
}
You are missing the point of opDispatch. It is not runtime defined,
because the compiler statically decides to call opDispatch. The dynamic
part of opDispatch comes if you want to do something based on runtime
values within the opDispatch function. e.g. the compiler doesn't decide
at *runtime* whether to call opDispatch or some normal function named
quack, it's decided at compile time. opDispatch could be completely
compile-time defined since it is a template. But the 'dynamicness' of
it is basically no more dynamic than a normal function which does
something based on runtime values.
Compare that to a dynamic language with which you can add methods to any
object instance to make it different than another object, or make it
conform to some interface.
Well, I believe it's possible to implement the same with opDispatch (not
just to any object, but to those that support it):
void foo() {}
Dynamic d = ..;
if (!d.foo) {
d.foo = &foo;
}
d.foo();