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