Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

multiple dispatch

Name: Anonymous 2012-01-21 4:10

Lisp:


[1]> (defclass B () ())
#<STANDARD-CLASS B>
[2]> (defclass C () ())
#<STANDARD-CLASS C>
[3]> (defgeneric f (x y))
#<STANDARD-GENERIC-FUNCTION F>
[4]> (defmethod f ((x B) (y B)) (print "BB"))
#<STANDARD-METHOD (#<STANDARD-CLASS B> #<STANDARD-CLASS B>)>
[5]> (defmethod f ((x B) (y C)) (print "BC"))
#<STANDARD-METHOD (#<STANDARD-CLASS B> #<STANDARD-CLASS C>)>
[6]> (defmethod f ((x C) (y B)) (print "CB"))
#<STANDARD-METHOD (#<STANDARD-CLASS C> #<STANDARD-CLASS B>)>
[7]> (defmethod f ((x C) (y C)) (print "CC"))
#<STANDARD-METHOD (#<STANDARD-CLASS C> #<STANDARD-CLASS C>)>
[8]> (f (make-instance 'B) (make-instance 'B))

"BB"
"BB"
[9]> (f (make-instance 'B) (make-instance 'C))

"BC"
"BC"
[10]> (f (make-instance 'C) (make-instance 'B))

"CB"
"CB"
[11]> (f (make-instance 'C) (make-instance 'C))

"CC"
"CC"
[12]>
Bye.


C++:


#include <iostream>

using namespace std;

struct A;
struct B;
struct C;

struct A {
  virtual ~A() {}

  virtual void f(A* y) = 0;

  virtual void f(B* y) = 0;
  virtual void f(C* y) = 0;

  virtual void g(B* y) = 0;
  virtual void g(C* y) = 0;
};

struct B : public A {
  void f(A* y);

  void f(B* y);
  void f(C* y);

  void g(B* y);
  void g(C* y);
};

struct C : public A {
  void f(A* y);

  void f(B* y);
  void f(C* y);

  void g(B* y);
  void g(C* y);
};

void B::f(A* y) { y->g(this); }

void B::f(B* y) { cout << "BB" << endl; }
void B::f(C* y) { cout << "BC" << endl; }

void B::g(B* y) { y->f(this); }
void B::g(C* y) { y->f(this); }


void C::f(A* y) { y->g(this); }

void C::f(B* y) { cout << "CB" << endl; }
void C::f(C* y) { cout << "CC" << endl; }

void C::g(B* y) { y->f(this); }
void C::g(C* y) { y->f(this); }

int main(int argc, char** argv) {
  A* b = new B();
  A* c = new C();
  b->f(b);
  b->f(c);
  c->f(b);
  c->f(c);
  delete b;
  delete c;
  return 0;


$ g++ gen.cpp
$ a.out
BB
BC
CB
CC

Name: Anonymous 2012-01-21 16:37

>>11
Actually I do, ``faggot''. It's when a different function or method is called depending on the types of all the arguments instead of just the invocant. In case you're a mental midget, (B){} and (C){} are compound literals. The B and C are types. A generic selection in C is the same as compile-time function overloading. If I used f_BB, f_BC, etc. instead of calling puts directly, it would be no different than C++ name mangling. Run-time multiple dispatch in C is usually done by using a tagged union of structs and then calling a different function depending on the type tag of each, or by using an array of function pointers for virtual functions.
#include <stdio.h>

typedef struct {
     enum Type { B, C } T;
     union {
          struct B {int dummy;} B;
          struct C {float dummy;} C;
     };
} Multi;

Multi B_ctr(int n) {return (Multi){B, .B.dummy = n};}
Multi C_ctr(float n) {return (Multi){C, .C.dummy = n};}

void f(Multi x, Multi y) {
     switch (x.T) {
          case B:switch (y.T) {
               case B:puts("BB");
               break;
               case C:puts("BC");
          }
          break;
          case C:switch (y.T) {
               case B:puts("CB");
               break;
               case C:puts("CC");
          }
     }
}

int main(void) {
     Multi B = B_ctr(0);
     Multi C = C_ctr(0);
     f(B,B);
     f(B,C);
     f(C,B);
     f(C,C);
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List