dynamic classes and duck typing

Denis Koroskin 2korden at gmail.com
Tue Dec 1 08:20:06 PST 2009


On Tue, 01 Dec 2009 19:02:27 +0300, Steven Schveighoffer  
<schveiguy at yahoo.com> wrote:

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



More information about the Digitalmars-d mailing list