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