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