[comp.lang.eiffel] Multi-methods in Eiffel

guenter@prism.gatech.EDU (Brian Guenter) (07/26/90)

I have recently been attempting to write a general purpose matrix arithmetic
package in Eiffel. The lack of multimethods, or I guess they would be called
multifeatures in Eiffel, makes it quite difficult to do this. For those
who aren't familiar with CLOS (which I know has multimethods) or C++ (which
I have been told has multimethods) multimethods allow discrimination on 
more than one argument. In Eiffel currently the discrimination is only on
the type of the object for which the feature application is being performed.
So if you want to define the infix operator * to handle these cases

matrix * matrix
matrix * constant
constant * matrix
vector * matrix
matrix * vector

you can do it for any one of the cases but not for all five at once. In CLOS
you would define a generic function * with specific implementations for each
of the 5 cases above based on the types of both arguments to the * function.
The compiler and run time system then choose the correct implementation 
depending on the type of the first two arguments to the * function.

In Eiffel in the class MATRIX there can only be one definition of the
* function. Three definitions are needed to handle all the cases involving
a matrix as the first argument.

In CLOS the definition would look something like this:

(defgeneric * arg1 arg2)

This defines the generic function * with two arguments. Then each of the
particular cases would have its own implementation 

(defmethod * ((arg1 MATRIX) (arg2 MATRIX))
	body of the method does matrix times matrix

(defmethod * ((arg1 MATRIX) (arg2 VECTOR))
	body of the method does matrix times vector

and so on.
	
The equivalent in Eiffel would look something like this:

class MATRIX

feature

infix '*' (arg:MATRIX):MATRIX is
do
	body of the feature does matrix matrix multiply
end;

infix '*' (arg:VECTOR):VECTOR is
do
	body of the feature does matrix vector multiply
end;

infix '*' (arg:REAL):MATRIX is
do
	body of the feature does matrix scalar multiply
end;

The compiler would then have to generate code to determine the type of
the argument at run time and then choose the appropriate implementation of *.

Of course the current Eiffel compiler doesn't allow this kind of thing. It 
seems to be a very useful feature however and I would like to know if there
is some overwhelmingly good reason why Eiffel doesn't have it, especially
since other OO languages do have this feature. Anybody from ISE care 
to comment?
-- 
Brian Guenter
Information and Computer Science
Georgia Institute of Technology, Atlanta Georgia, 30332-0280
Internet: guenter@cs.gatech.edu

johnson@m.cs.uiuc.edu (07/27/90)

I'm not from ISE, but I will comment on how to get the effect of
multimethods.  It is an easy (and, to me, standard) programming
technique called double dispatching.  It has a number of disadvantages,
but I consider them minor.  Kurt Hebel and I wrote an article on the
subject that appears in one of the recent issues of JOOP.

The basic idea is that you implement a binary operation like * by
sending a message to the argument.  The type of the original receiver
is encoded in the name of the message.  Thus, if you have 10 arithmetic
classes then you have ten messages of the form productOfInteger,
productOfReal, productOfMatrix, etc.  Each of the 10 classes has to
implement each of the 10 methods, so you end up with 100 methods.
Of course, you would have needed 100 multimethods, so it really
isn't any different.  You can generally eliminate a lot of the
multimethods using inheritance, but then you can do the same thing
with double dispatching, too.  The article gives details.

Multimethods and double dispatching are isomorphic.  One is a language
feature, the other is a programming technique.  In my opinion, the
need for selecting a method based on the type of more than one argument
is rare enough that it is probably not worth worrying about putting
multimethods in a language like Eiffel.

Ralph Johnson -- University of Illinois at Urbana-Champaign