www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Proposal

reply Matthias Becker <Matthias_member pathlink.com> writes:
I know that until version 1.0 no extensions to the core language are planed.
Someday there 

will be a D 2.0 which migth have some extensions. So I start collecting ideas.


Normaly you have to use code like this:

void foo (Base bar)
{
Derived1 derived1 = cast(Derived1)bar;
if (derived1 !== null) {
..
}

Derived2 derived2 = cast(Derived2)bar;
if (derived2 !== null) {
..
} 
}

This is very unconvenient. I propose extending switch so you can use it for 

type-dispatching:

void foo (Base bar)
{
switch (bar) {
case Derived1 derived1:
..
break;

case Derived2 derived2:
..
break; 
}

IMO this would fit perfectly into the language and doesn't cause any ambinguity.


------------------------------------

I have another much more flexible and more extendible idea, but I think it's
harder to 

implement and I don't know if Walter will like it.


Currently you can overload functions at compiletime. I propose an extension to
allow dynamic 

overloading that chooses the right function at runtime. Each function-argument
can have a 

dynamic type additionaly to the static type we already have:

// no changes here; this is used as a fallback
void foo (Base x) {...} 

// if the type at runtime is Derived this function is called
void foo (Base  Derived x) {...}  



This would allow to write multi-dispatchers in a convenient and easy extendible
way:

class Shape            {...};
class Square   : Shape {...};
class Triangle : Shape {...};

bool overlap (Shape a, Shape b) {...}

bool overlap (Shape  Square   a, Shape  Triangle b) {...}
bool overlap (Shape  Triangle a, Shape  Square   b) {...}


As I like functional programming, I'd like to go a step further in direction of
patter 

matching. I'd like to allow concret values instead of types. So you can write
special 

handlers for special situations.

enum State {running, stopped}

void handle (State   running) {...}
void handle (State   stopped) {...}


This can make code much more easy to read.


This idea is much more powerfull than the switch idea:

class Handler {
void handle (Event e) {...}
}

class ExtendedHandler : Handler {
void handle (Event  AnEvent e) {...}
void handle (Event  AnotherEvent e) {...}
}

class SpecialisedHandler : ExtendedHandler {
void handle (Event  SpecialEvent e) {...}
}


As you see, you can easily extend the proposed dynamic dispatchers, while you
can't do this 

with the switch-idea.


------------------------------------

While these two ideas don't exclude each other, I don't know, if it would be
usefull to have 

them both.
Jul 10 2004
next sibling parent Ben Hinkle <bhinkle4 juno.com> writes:
Matthias Becker wrote:

 I know that until version 1.0 no extensions to the core language are
 planed. Someday there
 
 will be a D 2.0 which migth have some extensions. So I start collecting
 ideas.
 
 
 Normaly you have to use code like this:
 
 void foo (Base bar)
 {
 Derived1 derived1 = cast(Derived1)bar;
 if (derived1 !== null) {
 ..
 }
 
 Derived2 derived2 = cast(Derived2)bar;
 if (derived2 !== null) {
 ..
 }
 }
 
 This is very unconvenient. I propose extending switch so you can use it
 for
 
 type-dispatching:
 
 void foo (Base bar)
 {
 switch (bar) {
 case Derived1 derived1:
 ..
 break;
 
 case Derived2 derived2:
 ..
 break;
 }
 
 IMO this would fit perfectly into the language and doesn't cause any
 ambinguity.

Interesting idea but basically this what dynamic function dispatching is for. What if a user added Derived3? They would have to go and add another case to your switch statement.
 ------------------------------------
 
 I have another much more flexible and more extendible idea, but I think
 it's harder to
 
 implement and I don't know if Walter will like it.
 
 
 Currently you can overload functions at compiletime. I propose an
 extension to allow dynamic
 
 overloading that chooses the right function at runtime. Each
 function-argument can have a
 
 dynamic type additionaly to the static type we already have:
 
 // no changes here; this is used as a fallback
 void foo (Base x) {...}
 
 // if the type at runtime is Derived this function is called
 void foo (Base  Derived x) {...}
 
 
 
 This would allow to write multi-dispatchers in a convenient and easy
 extendible way:
 
 class Shape            {...};
 class Square   : Shape {...};
 class Triangle : Shape {...};
 
 bool overlap (Shape a, Shape b) {...}
 
 bool overlap (Shape  Square   a, Shape  Triangle b) {...}
 bool overlap (Shape  Triangle a, Shape  Square   b) {...}
 

Double-dispatching, or more generally multiple dispatching, is pretty neat and you can google around for various techniques to do it in a single-dispatching language. For example here's a way that uses a table of fcn pointers indexed by ClassInfo. import std.stdio; class Shape { }; class Square:Shape { }; class Triangle:Shape { }; void overlapST(Square a, Triangle b) { writefln("square triangle"); } void overlapTS(Triangle a,Square b) { writefln("triangle square"); } void overlapTT(Triangle a,Triangle b) { writefln("triangle triangle"); } void overlapSS(Square a,Square b) { writefln("square square"); } alias void function(Shape a, Shape b) overlapFcn; overlapFcn[ClassInfo][ClassInfo] overlapFcnTable; static this() { overlapFcnTable[Square.classinfo][Triangle.classinfo] = cast(overlapFcn)&overlapST; overlapFcnTable[Triangle.classinfo][Square.classinfo] = cast(overlapFcn)&overlapTS; overlapFcnTable[Square.classinfo][Square.classinfo] = cast(overlapFcn)&overlapSS; overlapFcnTable[Triangle.classinfo][Triangle.classinfo] = cast(overlapFcn)&overlapTT; } void overlap(Shape x, Shape y) { overlapFcn f = overlapFcnTable[x.classinfo][y.classinfo]; if (f !== null) f(x,y); } int main() { Shape x = new Triangle(); Shape y = new Square(); overlap(x,y); overlap(y,y); return 0; } Should the language support this directly? maybe. it would be neat to try it out. It could just end making the language more confusing, though, with overloading rules and overriding rules mixed up together.
 As I like functional programming, I'd like to go a step further in
 direction of patter
 
 matching. I'd like to allow concret values instead of types. So you can
 write special
 
 handlers for special situations.
 
 enum State {running, stopped}
 
 void handle (State   running) {...}
 void handle (State   stopped) {...}
 
 
 This can make code much more easy to read.

 
 This idea is much more powerfull than the switch idea:
 
 class Handler {
 void handle (Event e) {...}
 }
 
 class ExtendedHandler : Handler {
 void handle (Event  AnEvent e) {...}
 void handle (Event  AnotherEvent e) {...}
 }
 
 class SpecialisedHandler : ExtendedHandler {
 void handle (Event  SpecialEvent e) {...}
 }

 As you see, you can easily extend the proposed dynamic dispatchers, while
 you can't do this
 
 with the switch-idea.

Jul 10 2004
prev sibling parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Matthias Becker wrote:

 Currently you can overload functions at compiletime. I propose an
 extension to allow dynamic overloading that chooses the right function at
 runtime. Each function-argument can have a dynamic type additionaly to the
 static type we already have:...

On the on hand, this is a very useful feature. I only have some fears concerning the programming style that follows from it and the effects for large projects: Reading through code that makes extensive use of dynamic dispatching, it may be really difficult to find the function that is called as some point. In dynamic dispatching, always that function is called which fits the arguments "best". With all the functions possibly being distributed over the whole source, you really have to know very well which function might be defined somewhere. In principle, you have the same thing for templates already, but here, it is resolved at compile time. This might not be a reason for not implementing dynamic dispatching, just a feeling, telling me that we should be careful.
Jul 11 2004
parent "Kris" <someidiot earthlink.dot.dot.dot.net> writes:
This kind of thing requires an immense level of care and attention over
time; just think back to how unmaintainable all those basic and cobol
programs were that used indirect goto's & gosub's ... there really ought to
be a law against certain coding practices, just as there is (in some places)
a law against many other activities ... <g>


"Norbert Nemec" <Norbert.Nemec gmx.de> wrote in message
news:ccqprc$69i$1 digitaldaemon.com...
 Matthias Becker wrote:

 Currently you can overload functions at compiletime. I propose an
 extension to allow dynamic overloading that chooses the right function


 runtime. Each function-argument can have a dynamic type additionaly to


 static type we already have:...

On the on hand, this is a very useful feature. I only have some fears concerning the programming style that follows from it and the effects for large projects: Reading through code that makes extensive use of dynamic dispatching, it

 be really difficult to find the function that is called as some point. In
 dynamic dispatching, always that function is called which fits the
 arguments "best". With all the functions possibly being distributed over
 the whole source, you really have to know very well which function might

 defined somewhere.

 In principle, you have the same thing for templates already, but here, it

 resolved at compile time.

 This might not be a reason for not implementing dynamic dispatching, just

 feeling, telling me that we should be careful.

Jul 11 2004