Multiple dispatch in lib was Re: Old comments about Java

KennyTM~ kennytm at gmail.com
Sun Apr 24 02:27:16 PDT 2011


On Apr 24, 11 09:30, Adam D. Ruppe wrote:
> bearophile wrote:
>> [multiple dispatch and what they use it for.]
>
> I wonder if we could do it in the library by using overloads and
> a generated dynamic cast.
>
> class Base {
>    // if the types are known, regular overloading does the job
>    void multipleDispatchFun(A a, A b) { writeln("Called (A, A)"); }
>    void multipleDispatchFun(A a, B b) { writeln("Called (A, B)"); }
>    void multipleDispatchFun(B a, B b) { writeln("Called (B, B)"); }
> }
>

This thing is a triple-dispatch. I think these should be static functions?

BTW, you toy example is way too long. 40 lines of template mixin is  enough:

import std.traits, std.typetuple;
template GeneralizeType(T) {
     static if (is(T == class))
         alias Object GeneralizeType;
         //@@@BUG@@@ Should preserve qualifier of T.
     else
         alias T GeneralizeType;
}
mixin template ImplementMultipleDispatch(alias method, alias Parent = 
__traits(parent, method)) {
     private enum methodName = __traits(identifier, method);
     private alias staticMap!(GeneralizeType, ParameterTypeTuple!method) 
ParamType;
     //@@@BUG3543@@@ Should take the most common type from all overloads 
of the
     //              method, but currently it is very complicated due to 
3543, so
     //              we just default to use Object.
     alias method opCall;
     static auto opCall(ParamType params) {
         writeln(" ***called the multiple dispatch method");
         foreach (overloadedMethod; __traits(getOverloads, Parent, 
methodName)) {
             //@@@BUG@@@ Should sort overloads by specialization.
             //@@@BUG@@@ Should inherit function attributes from the method
             ParameterTypeTuple!overloadedMethod specializedParam;
             bool matched = true;
             foreach (i, T; ParameterTypeTuple!overloadedMethod) {
                 specializedParam[i] = cast(T)params[i];
                 static if (is(T == class))
                     if (specializedParam[i] is null) {
                         //@@@BUG@@@ What if it is not a parameter for 
dispatch
                         //          but is null? Need to check that.
                         matched = false;
                         break;  // continue label doesn't work.
                     }
             }
             if (matched)
                 return overloadedMethod(specializedParam);
         }
         throw new Exception("Cannot find suitable overload in " ~ 
methodName);
     }
}

//------------------------------------------------------------------------------

import std.stdio;

class A : Base {}
class B : Base {}

class Base {
     static private {
         int someFuncImpl(A x, A y, B z, B w, double t) {
             writeln("A, A, B, B, ", t);
             return 3;
         }
         int someFuncImpl(A x, B y, A z, B w, double t) {
             writeln("A, B, A, B, ", t);
             return 2;
         }
         int someFuncImpl(A x, A y, A z, A w, double t) {
             writeln("A, A, A, A, ", t);
             return 1;
         }
     }

     mixin ImplementMultipleDispatch!someFuncImpl someFunc;
}

void main() {
	Base base = new Base();
	Base a = new A();
	Base b = new B();
     A aa = new A();
     B bb = new B();

     assert(1 == Base.someFunc(aa, aa, aa, aa, 0.4));
     assert(3 == Base.someFunc(aa, aa, bb, bb, 0.3));

     assert(1 == Base.someFunc(a, a, a, a, 0.5));
     assert(3 == Base.someFunc(a, a, b, b, 0.6));
     assert(2 == Base.someFunc(a, b, a, b, 0.7));
     Base.someFunc(b, b, b, b, 0.8);  // throws
}


More information about the Digitalmars-d mailing list