December 01, 2009
On Tue, 01 Dec 2009 16:46:25 +0300, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> On Mon, 30 Nov 2009 23:32:21 -0500, Bill Baxter <wbaxter@gmail.com> wrote:
>
>> On Mon, Nov 30, 2009 at 7:12 PM, Walter Bright
>> <newshound1@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.
December 01, 2009
On Tue, Dec 01, 2009 at 03:55:31PM +0300, Denis Koroskin wrote:
> I believe there will soon be a library type that would allow that.

Here's my first try. I don't have the the new compiler handy and am in a rush, so I'm doing it hacky.

With the svn compiler, you should be able to almost run this like you'd expect.

Running it prints:
	Running statically defined: test(10)
	Running dynamically defined test(0)
	object.Exception: no such method text

My vararg code apparently is broken, but meh.


========

import std.stdio;
import std.variant;
import std.stdarg;

class A { // this is our dynamic class
	void test(int a) {
		writefln("Running statically defined: test(%d)", a);
	}

	// Just like in javascript...
	A delegate(...)[string] dynamicFunctions;

	// Return value tells if we should forward to static methods
	bool dynamicCall(string name, out A ret, ...) {
		if(auto fun = name in dynamicFunctions) {
			ret = (*fun)(_arguments);
			return true;
		}

		return false;
	}

	void dynamicBind(string name, A delegate(...) fun) {
		dynamicFunctions[name] = fun;
	}

	A opDispatch(string a)(...) {
		// If we're assigning a delegate, bind it as a member
		if(_arguments[0] == typeid(A delegate(...))) {
			dynamicBind(a, *(cast(A delegate(...)*)(_argptr)));
			return null;
		}

		// If it is in the dynamic list, run that
		A ret;
		if(dynamicCall(a, ret, _arguments))
			return ret;

		// If not, we'll look it up in our static table

		int arg = va_arg!(int)(_argptr);
		static if(__traits(hasMember, this, a)) {
			A var;


			// gah, I wish auto var = fun() worked when fun returns
			// void.
			static if(__traits(compiles,
			    var = __traits(getMember, this, a)(arg)))
				return __traits(getMember, this, a)(arg);
			else {
				// Could be improved by trying to construct a
				// dynamic instance from the return value,
				// whatever it is
				__traits(getMember, this, a)(arg);
				return null;
			}
		}
		else
			throw new Exception("no such method " ~ a);
	}
}

void main() {
	A a = new A;

	// no dynamically defined members, so this should call the static
	a.opDispatch!("test")(10);

	// dynamically define a member to override the static one
	a.opDispatch!("test")(delegate A(int num) {
		writefln("Running dynamically defined test(%d)", num);
		return null;
	});

	// see what runs
	a.opDispatch!("test")(20);

	// should throw method not defined
	a.opDispatch!("text")(30);
}

=========

If you have the svn compiler, you should be able to replace those opDispatchs
with
	a.test = 10;
and stuff like that.



There's one thing though: I think the patch checks static stuff first, then if none of that matches, it forwards to opDispatch.

For this to work like in Javascript, it will need a small change.


1) If opDispatch is defined, forward the method do it
2) If this compiles, do nothing more -- assume the opDispatch handled it
3) If not, do a normal static member lookup

If opDispatch is not defined for the class, do nothing special - treat it like you normally do in D.


The downside is you must either put a static constraint on what your opDispatch does (easy - static assert(0); if you don't handle it) or forward to your static members yourself, but the upside is it lets dynamic method overriding like I do here.

I think it would be a net positive. Assuming this doesn't work already, of course.

-- 
Adam D. Ruppe
http://arsdnet.net
December 01, 2009
On Sat, 28 Nov 2009 18:36:07 -0500, Walter Bright <newshound1@digitalmars.com> wrote:

> And here it is (called opDispatch, Michel Fortin's suggestion):
>
> http://www.dsource.org/projects/dmd/changeset?new=trunk%2Fsrc@268&old=trunk%2Fsrc@267

I have a few questions:

1. How should the compiler restrict opDispatch's string argument?  i.e. if I implement opDispatch, I'm normally expecting the string to be a symbol, but one can directly call opDispatch with any string (I can see clever usages which compile but for instance circumvent const or something), forcing me to always constrain the string argument, i.e. always have isValidSymbol(s) in my constraints.  Should the compiler restrict the string to always being a valid symbol name (or operator, see question 2)?

2. Can we cover templated operators with opDispatch?  I can envision something like this:

opDispatch(string s)(int rhs) if(s == "+") {...}

I'm still hesitant on operators only being definable through templates, since it makes for very ugly and complex function signatures, regardless of whether they are virtual or not.  I would be all for it if you can make shortcuts like:

operator("+")(int rhs)

hm.. that gives me an idea.  new post...

-Steve
December 01, 2009
Bill Baxter wrote:

> On Tue, Dec 1, 2009 at 5:38 AM, Bill Baxter <wbaxter@gmail.com> wrote:
>> On Tue, Dec 1, 2009 at 5:18 AM, Lutger <lutger.blijdestijn@gmail.com> wrote:
>>> Ary Borenszweig wrote:
>>>
>>>> Denis Koroskin wrote:
>>>>> On Tue, 01 Dec 2009 15:05:16 +0300, Ary Borenszweig <ary@esperanto.org.ar> wrote:
>>>>>
>>>>>> Ary Borenszweig wrote:
>>>>>>> retard wrote:
>>>>>>>> Tue, 01 Dec 2009 03:16:47 -0800, Walter Bright wrote:
>>>>>>>>
>>>>>>>>> Ary Borenszweig wrote:
>>>>>>>>>> Can you show examples of points 2, 3 and 4?
>>>>>>>>> Have opDispatch look up the string in an associative array that
>>>>>>>>> returns
>>>>>>>>> an associated delegate, then call the delegate.
>>>>>>>>>
>>>>>>>>> The dynamic part will be loading up the associative array at run time.
>>>>>>>>
>>>>>>>> This is not exactly what everyone of us expected. I'd like to have something like
>>>>>>>>
>>>>>>>> void foo(Object o) {
>>>>>>>> o.duckMethod();
>>>>>>>> }
>>>>>>>>
>>>>>>>> foo(new Object() { void duckMethod() {} });
>>>>>>>>
>>>>>>>> The feature isn't very dynamic since the dispatch rules are defined statically. The only thing you can do is rewire the associative array when forwarding statically precalculated dispatching.
>>>>>>> Exactly! That's the kind of example I was looking for, thanks.
>>>>>>
>>>>>> Actuall, just the first part of the example:
>>>>>>
>>>>>> void foo(Object o) {
>>>>>> o.duckMethod();
>>>>>> }
>>>>>>
>>>>>> Can't do that because even if the real instance of Object has an opDispatch method, it'll give a compile-time error because Object does not defines duckMethod.
>>>>>>
>>>>>> That's why this is something useful in scripting languages (or ruby, python, etc.): if the method is not defined at runtime it's an error unless you define the magic function that catches all. Can't do that in D because the lookup is done at runtime.
>>>>>>
>>>>>> Basically:
>>>>>>
>>>>>> Dynanic d = ...;
>>>>>> d.something(1, 2, 3);
>>>>>>
>>>>>> is just a shortcut for doing
>>>>>>
>>>>>> d.opDispatch!("something")(1, 2, 3);
>>>>>>
>>>>>> (and it's actually what the compiler does) but it's a standarized way of doing that. What's the fun in that?
>>>>>
>>>>> The fun is that you can call d.foo and d.bar() even though there is no
>>>>> such method/property.
>>>>>
>>>>> In ActionScript (and JavaScript, too, I assume), foo.bar is auto-magically rewritten as foo["bar"]. What's fun in that?
>>>>
>>>> The fun is that in Javascript I can do:
>>>>
>>>> ---
>>>> function yourMagicFunction(d) {
>>>> d.foo();
>>>> }
>>>>
>>>> var something = fromSomewhere();
>>>> yourMagicFunction(something);
>>>> ---
>>>>
>>>> and it'll work in Javascript because there's no type-checking at compile-time (well, because there's no compile-time :P)
>>>>
>>>> Let's translate this to D:
>>>>
>>>> ---
>>>> void yourMagicFunction(WhatTypeToPutHere d) {
>>>> d.foo();
>>>> }
>>>>
>>>> auto something = fromSomewhere();
>>>> yourMagicFunction(something);
>>>> ---
>>>>
>>>> What type to put in "WhatTypeToPutHere"? If it's Object then it won't compile. If it's something that defines foo, ok. If it's something that defines opDispatch, then it's:
>>>>
>>>> d.opDispatch("foo")();
>>>>
>>>> but you could have written it like that from the beginning.
>>>>
>>>> So for now I see two uses for opDispatch:
>>>>
>>>> 1. To create a bunch of similar functions, like the swizzle one.
>>>> 2. To be able to refactor a class by moving a method to opDispatch or
>>>> viceversa:
>>>>
>>>> class Something {
>>>> void foo() { }
>>>> }
>>>>
>>>> can be refactored to:
>>>>
>>>> class Something {
>>>> void opDispatch(string name) if (name == "foo") {}
>>>> }
>>>>
>>>> without problems on the client side either way.
>>>>
>>>> In brief, when you see:
>>>>
>>>> var x = ...;
>>>> x.foo();
>>>>
>>>> in Javascript, you have no idea where foo could be defined.
>>>>
>>>> If you see the same code in D you know where to look for: the class itself, it's hierarchy, alias this, opDispatch. That's a *huge* difference.
>>>
>>> I don't get it, what if WhatTypeToPutHere does a dynamic lookup, then it's pretty much the same a Javascript isn't it? Except that everything in Javascript does dynamic lookup and in D you are restricted to types that have this dynamic lookup (which, pending a phobos solution you have to code yourself). Do you mean to say this 'except' is the obstacle somehow?
>>>
>>> To say it in code:
>>>
>>> void yourMagicDFunction(T)(T d)
>>> if ( ImplementsFooOrDispatch!T )
>>> {
>>> d.foo(); // may (or not) be rewritten as d.opDispatch!"foo"
>>> }
>>>
>>> In javascript I understand it is like this:
>>>
>>> void yourMagicJavascriptFunction(T d)
>>> {
>>> d.foo(); // rewritten as d["foo"]
>>> }
>>>
>>> But with opDisptach implemented like this it is the same in D:
>>>
>>> class DynamicThing
>>> {
>>> void opDispatch(string name)()
>>> {
>>> auto func = this.lookupTable[name]; // looks up 'foo'
>>> func(); //
>>> }
>>> }
>>>
>>> How is that less dynamic? You would be able to call or even redefine at runtime, for example, signals defined in xml files used to build gui components.
>>
>> It is a bit less dynamic because in D it's all done with templates.
>> For instance in Javascript you can easily pass
>> yourMagicJavascriptFunction around to other functions.
>> And you can rebind the method by setting  d.foo = &someOtherFunction.
>> Instead of d.lookupTable["foo"] = &someOtherFunction.
>>
>> But I'm not sure such differences make a big impact on any major class of use cases.
> 
> I forgot a biggie: with opDispatch you must know the return type at
> compile time.
> You could make the return type be Variant or something, but then that
> makes it quite different from a "regular" function.
> Whereas in a dynamic language like Javascript a dynamic method looks
> just like a regular method (because they're all dynamic, of course).
> 
> --bb

I understand, thanks for the clarifications.

Variant doesn't sound too bad. I guess it's just the consequence of not overloading by return type.

What I like about this solution is the leeway you have in how much typechecking opDispatch does. You can make the return type Variant and the parameters a variadics of Variant (is that a word?), but also define the signature opDispatch can accept precisely or through template constraints. You can even check the dispatched symbol at compile time (no dynamism at all).

Obviously opDispatch can add some dynamism to D, I guess we'll see how it pans out.
December 01, 2009
On Tue, 01 Dec 2009 08:49:58 -0500, Denis Koroskin <2korden@gmail.com> wrote:

> On Tue, 01 Dec 2009 16:46:25 +0300, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>
>> On Mon, 30 Nov 2009 23:32:21 -0500, Bill Baxter <wbaxter@gmail.com> wrote:
>>
>>> On Mon, Nov 30, 2009 at 7:12 PM, Walter Bright
>>> <newshound1@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
December 01, 2009
Lutger wrote:
> Bill Baxter wrote:
> 
>> On Tue, Dec 1, 2009 at 5:38 AM, Bill Baxter <wbaxter@gmail.com> wrote:
>>> On Tue, Dec 1, 2009 at 5:18 AM, Lutger <lutger.blijdestijn@gmail.com>
>>> wrote:
>>>> Ary Borenszweig wrote:
>>>>
>>>>> Denis Koroskin wrote:
>>>>>> On Tue, 01 Dec 2009 15:05:16 +0300, Ary Borenszweig
>>>>>> <ary@esperanto.org.ar> wrote:
>>>>>>
>>>>>>> Ary Borenszweig wrote:
>>>>>>>> retard wrote:
>>>>>>>>> Tue, 01 Dec 2009 03:16:47 -0800, Walter Bright wrote:
>>>>>>>>>
>>>>>>>>>> Ary Borenszweig wrote:
>>>>>>>>>>> Can you show examples of points 2, 3 and 4?
>>>>>>>>>> Have opDispatch look up the string in an associative array that
>>>>>>>>>> returns
>>>>>>>>>> an associated delegate, then call the delegate.
>>>>>>>>>>
>>>>>>>>>> The dynamic part will be loading up the associative array at run
>>>>>>>>>> time.
>>>>>>>>> This is not exactly what everyone of us expected. I'd like to have
>>>>>>>>> something like
>>>>>>>>>
>>>>>>>>> void foo(Object o) {
>>>>>>>>> o.duckMethod();
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> foo(new Object() { void duckMethod() {} });
>>>>>>>>>
>>>>>>>>> The feature isn't very dynamic since the dispatch rules are defined
>>>>>>>>> statically. The only thing you can do is rewire the associative
>>>>>>>>> array when forwarding statically precalculated dispatching.
>>>>>>>> Exactly! That's the kind of example I was looking for, thanks.
>>>>>>> Actuall, just the first part of the example:
>>>>>>>
>>>>>>> void foo(Object o) {
>>>>>>> o.duckMethod();
>>>>>>> }
>>>>>>>
>>>>>>> Can't do that because even if the real instance of Object has an
>>>>>>> opDispatch method, it'll give a compile-time error because Object
>>>>>>> does not defines duckMethod.
>>>>>>>
>>>>>>> That's why this is something useful in scripting languages (or ruby,
>>>>>>> python, etc.): if the method is not defined at runtime it's an error
>>>>>>> unless you define the magic function that catches all. Can't do that
>>>>>>> in D because the lookup is done at runtime.
>>>>>>>
>>>>>>> Basically:
>>>>>>>
>>>>>>> Dynanic d = ...;
>>>>>>> d.something(1, 2, 3);
>>>>>>>
>>>>>>> is just a shortcut for doing
>>>>>>>
>>>>>>> d.opDispatch!("something")(1, 2, 3);
>>>>>>>
>>>>>>> (and it's actually what the compiler does) but it's a standarized way
>>>>>>> of doing that. What's the fun in that?
>>>>>> The fun is that you can call d.foo and d.bar() even though there is no
>>>>>> such method/property.
>>>>>>
>>>>>> In ActionScript (and JavaScript, too, I assume), foo.bar is
>>>>>> auto-magically rewritten as foo["bar"]. What's fun in that?
>>>>> The fun is that in Javascript I can do:
>>>>>
>>>>> ---
>>>>> function yourMagicFunction(d) {
>>>>> d.foo();
>>>>> }
>>>>>
>>>>> var something = fromSomewhere();
>>>>> yourMagicFunction(something);
>>>>> ---
>>>>>
>>>>> and it'll work in Javascript because there's no type-checking at
>>>>> compile-time (well, because there's no compile-time :P)
>>>>>
>>>>> Let's translate this to D:
>>>>>
>>>>> ---
>>>>> void yourMagicFunction(WhatTypeToPutHere d) {
>>>>> d.foo();
>>>>> }
>>>>>
>>>>> auto something = fromSomewhere();
>>>>> yourMagicFunction(something);
>>>>> ---
>>>>>
>>>>> What type to put in "WhatTypeToPutHere"? If it's Object then it won't
>>>>> compile. If it's something that defines foo, ok. If it's something that
>>>>> defines opDispatch, then it's:
>>>>>
>>>>> d.opDispatch("foo")();
>>>>>
>>>>> but you could have written it like that from the beginning.
>>>>>
>>>>> So for now I see two uses for opDispatch:
>>>>>
>>>>> 1. To create a bunch of similar functions, like the swizzle one.
>>>>> 2. To be able to refactor a class by moving a method to opDispatch or
>>>>> viceversa:
>>>>>
>>>>> class Something {
>>>>> void foo() { }
>>>>> }
>>>>>
>>>>> can be refactored to:
>>>>>
>>>>> class Something {
>>>>> void opDispatch(string name) if (name == "foo") {}
>>>>> }
>>>>>
>>>>> without problems on the client side either way.
>>>>>
>>>>> In brief, when you see:
>>>>>
>>>>> var x = ...;
>>>>> x.foo();
>>>>>
>>>>> in Javascript, you have no idea where foo could be defined.
>>>>>
>>>>> If you see the same code in D you know where to look for: the class
>>>>> itself, it's hierarchy, alias this, opDispatch. That's a *huge*
>>>>> difference.
>>>> I don't get it, what if WhatTypeToPutHere does a dynamic lookup, then
>>>> it's pretty much the same a Javascript isn't it? Except that everything
>>>> in Javascript does dynamic lookup and in D you are restricted to types
>>>> that have this dynamic lookup (which, pending a phobos solution you have
>>>> to code yourself). Do you mean to say this 'except' is the obstacle
>>>> somehow?
>>>>
>>>> To say it in code:
>>>>
>>>> void yourMagicDFunction(T)(T d)
>>>> if ( ImplementsFooOrDispatch!T )
>>>> {
>>>> d.foo(); // may (or not) be rewritten as d.opDispatch!"foo"
>>>> }
>>>>
>>>> In javascript I understand it is like this:
>>>>
>>>> void yourMagicJavascriptFunction(T d)
>>>> {
>>>> d.foo(); // rewritten as d["foo"]
>>>> }
>>>>
>>>> But with opDisptach implemented like this it is the same in D:
>>>>
>>>> class DynamicThing
>>>> {
>>>> void opDispatch(string name)()
>>>> {
>>>> auto func = this.lookupTable[name]; // looks up 'foo'
>>>> func(); //
>>>> }
>>>> }
>>>>
>>>> How is that less dynamic? You would be able to call or even redefine at
>>>> runtime, for example, signals defined in xml files used to build gui
>>>> components.
>>> It is a bit less dynamic because in D it's all done with templates.
>>> For instance in Javascript you can easily pass
>>> yourMagicJavascriptFunction around to other functions.
>>> And you can rebind the method by setting  d.foo = &someOtherFunction.
>>> Instead of d.lookupTable["foo"] = &someOtherFunction.
>>>
>>> But I'm not sure such differences make a big impact on any major class
>>> of use cases.
>> I forgot a biggie: with opDispatch you must know the return type at
>> compile time.
>> You could make the return type be Variant or something, but then that
>> makes it quite different from a "regular" function.
>> Whereas in a dynamic language like Javascript a dynamic method looks
>> just like a regular method (because they're all dynamic, of course).
>>
>> --bb
> 
> I understand, thanks for the clarifications. 
> 
> Variant doesn't sound too bad. I guess it's just the consequence of not overloading by return type. 
> 
> What I like about this solution is the leeway you have in how much typechecking opDispatch does. You can make the return type Variant and the parameters a variadics of Variant (is that a word?), but also define the signature opDispatch can accept precisely or through template constraints. You can even check the dispatched symbol at compile time (no dynamism at all).
> 
> Obviously opDispatch can add some dynamism to D, I guess we'll see how it pans out.

So the return type is now suggested to be Variant.  Plausible expectation is that Variant is now input as argument to some another function.

So now you have a Variant to deal with as a function argument.  How now is Variant argument to be dealt with?  Question meaning typeswitch or something else?
December 01, 2009
On Tue, 01 Dec 2009 03:15:12 -0800, Walter Bright <newshound1@digitalmars.com> wrote:

>Max Samukha wrote:
>> On Mon, 30 Nov 2009 22:33:40 -0800, Walter Bright <newshound1@digitalmars.com> wrote:
>> 
>>> I agree. While the compiler currently doesn't check for mixing up properties and methods, I intend to make it do so. I can't see any justification for allowing it.
>> 
>> Bill rightfully mentioned that it would be impossible to dynamically dispatch to both properties and methods even if those properties and methods don't have conflicting names. And that may really be an unfortunate limitation. For example, it would be problematic to implement a generic wrapper for IDispatch:
>
>Is there any reason not to just make the IDispatch properties have a function interface?

I don't know. It looks like IDispatch::Invoke requires the invokation flag to be explicitly specified. The wrapper can try to determine the flag using IDispatch::GetTypeInfo. However, objects implementing IDispatch are not required to provide any type information.

Denis has suggested a convention-based approach (constraint for names starting with "prop_"). It is not great but may work.
December 01, 2009
Tue, 01 Dec 2009 15:14:56 +0200, Max Samukha wrote:

> On Tue, 1 Dec 2009 11:45:14 +0000 (UTC), retard <re@tard.com.invalid>
>>Agreed. But this new feature is a bit confusing - there isn't anything dynamic in it. It's more or less a compile time rewrite rule. It becomes dynamic when all of that can be done on runtime and there are no templates involved.
> 
> But the feature can be used to implement fully dynamic behavior (provided there is extended RTTI, which is already implementable on top of compiletime introspection using a tweaked compiler). For example, Variant can implement opDispatch to forward calls to the contained object:
> 
> void foo(Variant o) {
> 	o.duckMethod();
> }
> 
> foo(Variant(new class { void duckMethod() {} }));
> 
> BTW, it is not possible currently to create a Variant from a void pointer to the object and the meta-object of that object because D's meta-objects are lacking necessary information. But that is fixable, I guess.

Ok, good to know.
December 01, 2009
On Tue, 01 Dec 2009 17:12:38 +0300, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> On Tue, 01 Dec 2009 08:49:58 -0500, Denis Koroskin <2korden@gmail.com> wrote:
>
>> On Tue, 01 Dec 2009 16:46:25 +0300, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
>>
>>> On Mon, 30 Nov 2009 23:32:21 -0500, Bill Baxter <wbaxter@gmail.com> wrote:
>>>
>>>> On Mon, Nov 30, 2009 at 7:12 PM, Walter Bright
>>>> <newshound1@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():
}
December 01, 2009
On Tue, 01 Dec 2009 16:19:58 +0300, Denis Koroskin <2korden@gmail.com>
wrote:

> On Tue, 01 Dec 2009 16:08:18 +0300, Ary Borenszweig <ary@esperanto.org.ar> wrote:
>
>> Denis Koroskin wrote:
>>> On Tue, 01 Dec 2009 15:47:43 +0300, Ary Borenszweig <ary@esperanto.org.ar> wrote:
>>>
>>>> Denis Koroskin wrote:
>>>>> On Tue, 01 Dec 2009 15:05:16 +0300, Ary Borenszweig <ary@esperanto.org.ar> wrote:
>>>>>
>>>>>> Ary Borenszweig wrote:
>>>>>>> retard wrote:
>>>>>>>> Tue, 01 Dec 2009 03:16:47 -0800, Walter Bright wrote:
>>>>>>>>
>>>>>>>>> Ary Borenszweig wrote:
>>>>>>>>>> Can you show examples of points 2, 3 and 4?
>>>>>>>>> Have opDispatch look up the string in an associative array that returns
>>>>>>>>> an associated delegate, then call the delegate.
>>>>>>>>>
>>>>>>>>> The dynamic part will be loading up the associative array at run time.
>>>>>>>>
>>>>>>>> This is not exactly what everyone of us expected. I'd like to have something like
>>>>>>>>
>>>>>>>> void foo(Object o) {
>>>>>>>>   o.duckMethod();
>>>>>>>> }
>>>>>>>>
>>>>>>>> foo(new Object() { void duckMethod() {} });
>>>>>>>>
>>>>>>>> The feature isn't very dynamic since the dispatch rules are defined statically. The only thing you can do is rewire the associative array when forwarding statically precalculated dispatching.
>>>>>>>  Exactly! That's the kind of example I was looking for, thanks.
>>>>>>
>>>>>> Actuall, just the first part of the example:
>>>>>>
>>>>>> void foo(Object o) {
>>>>>>     o.duckMethod();
>>>>>> }
>>>>>>
>>>>>> Can't do that because even if the real instance of Object has an opDispatch method, it'll give a compile-time error because Object does not defines duckMethod.
>>>>>>
>>>>>> That's why this is something useful in scripting languages (or ruby, python, etc.): if the method is not defined at runtime it's an error unless you define the magic function that catches all. Can't do that in D because the lookup is done at runtime.
>>>>>>
>>>>>> Basically:
>>>>>>
>>>>>> Dynanic d = ...;
>>>>>> d.something(1, 2, 3);
>>>>>>
>>>>>> is just a shortcut for doing
>>>>>>
>>>>>> d.opDispatch!("something")(1, 2, 3);
>>>>>>
>>>>>> (and it's actually what the compiler does) but it's a standarized way of doing that. What's the fun in that?
>>>>>  The fun is that you can call d.foo and d.bar() even though there is no such method/property.
>>>>>  In ActionScript (and JavaScript, too, I assume), foo.bar is auto-magically rewritten as foo["bar"]. What's fun in that?
>>>>
>>>> The fun is that in Javascript I can do:
>>>>
>>>> ---
>>>> function yourMagicFunction(d) {
>>>>    d.foo();
>>>> }
>>>>
>>>> var something = fromSomewhere();
>>>> yourMagicFunction(something);
>>>> ---
>>>>
>>>> and it'll work in Javascript because there's no type-checking at compile-time (well, because there's no compile-time :P)
>>>>
>>>> Let's translate this to D:
>>>>
>>>> ---
>>>> void yourMagicFunction(WhatTypeToPutHere d) {
>>>>    d.foo();
>>>> }
>>>>
>>>> auto something = fromSomewhere();
>>>> yourMagicFunction(something);
>>>> ---
>>>>
>>>  I believe there will soon be a library type that would allow that.
>>
>> It's called a template:
>>
>> void yourMagicFunction(T)(T d) {
>>    d.foo();
>> }
>>
>> I can write that and I can always compile my code. I can use that function with any kind of symbol as long as it defines foo, whether it's by definining it explicitly, in it's hierarchy, in an aliased this symbol or in an opDispatch. That's the same concept as any function in Javascript (except that in Javascript if the argument doesn't define foo it's a runtime error and in D it'll be a compile-time error).
>
> No, I was thinking about a Dynamic class:
>
> class Foo {
>      void foo() { ... }
> }
>
> void yourMagicFunction(Dynamic d) {
>      d.foo(); // might throw if there is no such method in an underlying class
> }
>
> yourMagicFunction(new Dynamic(new Foo()));
>
> There are a few open issues, though: lack or true reflection and lack of overload by return type.
>
> For example, I'd like to do the following:
>
> Dynamic d = ...;
> d.foo = 42.0;
> int i = d.foo; // returns 42
> float f = d.foo; // return 42.f
>
> Overload by return type would allow that:
>
> RetType opDispatch(RetType, string method, Args...)(Args args)
> {
>      // ...
> }
>
> But relection is still needed to find out what methods a given object has:
>
> class Foo { void foo(float f) { ... } }
> Object o = new Foo();
>
> Dynamic d = new Dynamic(o);
> d.foo(-1); // should call o.foo(-1.0); but I see no way to implement it currently

On a second thought, overload by return type won't work since I'd like to
do the following:

Dynamic d = ..;
d = 42.5;

float f = d;  // f = 42.5f;
int i = d;    // d = 42

And this requires an opImplicitCast(T).

For a comparison, C# allows the following
(http://msdn.microsoft.com/en-us/library/dd264736(VS.100).aspx):

// Any object can be converted to dynamic type implicitly, as shown in the
// following examples:

dynamic d1 = 7;
dynamic d2 = "a string";
dynamic d3 = System.DateTime.Today;
dynamic d4 = System.Diagnostics.Process.GetProcesses();

// Conversely, an implicit conversion can be dynamically applied to any
// expression of type dynamic:

int i = d1;
string str = d2;
DateTime dt = d3;
System.Diagnostics.Process[] procs = d4;