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