dynamic classes and duck typing

Denis Koroskin 2korden at gmail.com
Tue Dec 1 07:30:06 PST 2009


On Tue, 01 Dec 2009 16:19:58 +0300, Denis Koroskin <2korden at gmail.com>
wrote:

> On Tue, 01 Dec 2009 16:08:18 +0300, Ary Borenszweig  
> <ary at esperanto.org.ar> wrote:
>
>> Denis Koroskin wrote:
>>> On Tue, 01 Dec 2009 15:47:43 +0300, Ary Borenszweig  
>>> <ary at esperanto.org.ar> wrote:
>>>
>>>> Denis Koroskin wrote:
>>>>> On Tue, 01 Dec 2009 15:05:16 +0300, Ary Borenszweig  
>>>>> <ary at 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;



More information about the Digitalmars-d mailing list