December 01, 2009
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).
December 01, 2009
2009/12/1 Ary Borenszweig <ary@esperanto.org.ar>:
> 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).

If you define a catch-all opDispatch that forwards to a method that does dynamic lookup, then the error will be a runtime error.

--bb
December 01, 2009
On Tue, 1 Dec 2009 11:45:14 +0000 (UTC), retard <re@tard.com.invalid>
wrote:

>>>
>>> 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.
>> 
>> I believe you should distinguish duck types from other types.
>> 
>> You shouldn't be able to call duckMethod given a reference to Object, it's a statically-typed language, after all.
>
>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.
December 01, 2009
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.




December 01, 2009
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
December 01, 2009
Bill Baxter wrote:
> 2009/12/1 Ary Borenszweig <ary@esperanto.org.ar>:
>> 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).
> 
> If you define a catch-all opDispatch that forwards to a method that
> does dynamic lookup, then the error will be a runtime error.
> 
> --bb
Which is correct, awesome, great, etc. Wouldn't want it any other way!
December 01, 2009
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.


--bb
December 01, 2009
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
December 01, 2009
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
December 01, 2009
Walter Bright, el 30 de noviembre a las 22:33 me escribiste:
> Andrei Alexandrescu wrote:
> >Bill Baxter 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.
> >>
> >>--bb
> >
> >It's a limitation similar to not having a field and a method share the same name. It avoids a number of awkward questions such as figuring the meaning of &s.x.
> 
> 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.

What about:

@property int opDispatch(string n)() if (n.startsWith("prop_"))
{
	// ...
}

int opDispatch(string n)() if (n.startsWith("meth_"))
{
	// ...
}

int i = o.prop_x;
int j = o.meth_x();

Should this work? Is not that pretty, but it's a compromise.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
Y tuve amores, que fue uno sólo
El que me dejó de a pie y me enseñó todo...