From: gadbois@mcc.com (David Gadbois)
Newsgroups: comp.lang.clos
Subject: Re: Beginner's Question - CLOS
Date: 19 Aug 92 14:09:00 GMT
Organization: The Ohio State University Department of Computer and Information Science


    Date: Wed, 19 Aug 1992 16:38 CDT
    From: eric@tfs.com (Eric Smith)

    In article <16u2tpINN9ad@early-bird.think.com> barmar@think.com (Barry Margolin) writes:
    >(defmethod display ((value real) (destination window))
    >  ... ;; code to display a real number graphically on a window
    >  )
    >
    >(defmethod display ((value integer) (destination terminal))
    >  ... ;; code to display an integer textually on a terminal
    >  )

    But doesn't that make method dispatch very time consuming?  It seems
    like it would involve searching for the method in tables, and that
    the amount of time consumed would depend on how many methods were in
    those tables and how many class arguments each method had.

In the general case, this is certainly true.  Method dispatch is usually
implemented via hashing on the types of the positional arguments.
(Things are actually a bit hairier because of method combination and the
possibility of redefinitions.)  There are lots of ways to bum the
lookup, so it is possible for it to take a fraction of a microsecond,
though maybe only on a 200 MHz machine.

If the compiler has more information (like inline and type declarations)
so that it knows the types of the arguments at compile time and that the
generic function will not change, then there is no reason it cannot just
call the code for the right statically compiled combined method.

So, you have the best of both worlds.  You can have somewhat slower,
completely dynamic lookup for rapid prototyping, incremental
development, and doing tricks like having a program define new classes
and add and remove methods on the fly.  Or, if you have a sufficiently
smart compiler and put in a little extra work giving it some hints, you
can get code about as tight as can be.

[I like the notion of freezing and sealing in Dylan even better, since
you don't have to spend so much time second-guessing how the compiler is
going to interpret declarations.]

    In C++, method dispatch is trivial to the CPU, such that on most
    modern CPU's it would take a fraction of a microsecond.  I can see
    the advantages of dispatching according to the types of multiple
    arguments, but I'm just wondering how much of a speed impact it has.
    In C++ the same functionality requires more code, but it seems like
    it would still be faster.  For example, a terminal object's display
    function would take a base class of data as its argument, and then
    it would get the data converted to its requirement by invoking a
    conversion method on the data object.  That conversion method would
    be known to the terminal object at compile time, so the resulting
    code would involve no lookups other than the initial sub-microsecond
    dispatch to the terminal object's display function, followed by the
    sub-microsecond dispatch to the data objects's conversion function
    for that terminal object's data format.

This sounds like a good argument *for* multimethods, since the
optimization mentioned above seems a lot easier to do than getting into
the terminal object's display function so as to go directly to the
data object's conversion function.

Another thing I have noticed is that, for languages that do not set out
from the start to optimize dynamically typed data, much less attention
is paid to optimizing the cases where it does occur, such as virtual
functions in C++ or union types in SML.  The penalty for using the
dynamic aspects of these languages is bigger than for just doing the
natural thing in Lispy languages because less effort is put into making
object representation, run-time type information, and dynamic
dispatching efficient.

--David Gadbois
Newsgroups: comp.lang.clos