Newsgroups: comp.object,comp.lang.c++,comp.lang.ada,comp.lang.clos
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!vixen.cso.uiuc.edu!uchinews!gw2.att.com!nntpa!not-for-mail
From: ka@socrates.hr.att.com (Kenneth Almquist)
Subject: Multiple dispatch  (was Re: C++ not OOP?)
Message-ID: <D71Gs9.2FG@nntpa.cb.att.com>
Sender: news@nntpa.cb.att.com (Netnews Administration)
Nntp-Posting-Host: socrates.hr.att.com
Organization: AT&T
References: <dewar.797512974@gnat> <3mbmd5$s06@icebox.mfltd.co.uk> <D6uA77.Lqp@mcshub.dcss.mcmaster.ca> <3mcfbf$psl@acmez.gatech.edu> <3mcoh6$add@Starbase.NeoSoft.COM> <3mdrpf$3o9@disunms.epfl.ch> <dewar.797608300@gnat> <3mg45s$5r7@disunms.epfl.ch> <3mjc8c$630@crcnis3.unl.edu>
Date: Fri, 14 Apr 1995 19:00:09 GMT
Lines: 91
Xref: glinda.oz.cs.cmu.edu comp.object:29599 comp.lang.c++:123262 comp.lang.ada:28590 comp.lang.clos:2868

swd@cse.unl.edu (Scot Dyer) writes:
> You know, I've seen quite a bit of this argument about single vs. multiple
> dispatch, but I've vary rarely seen an example of what multiple dispatch can
> do right that single dispatch can't do right.

A real example to discuss.  Excellent!

> Question:  Using single dispatch, how does one code a subroutine to display
> a given shape on a given device?
>
> [Discussion deleted]
>
> Solution:  In a language with multiple dispatch, one may write a function
> display( shape s, device d ) { ... } which does the trick.  Then when you
> add a shape you need to add display() methods for it and every device, and
> when you add a device you need to add display() methods for every shape.

Let's suppose that the only requests for added features for this software
will be requests for new shapes or new devices.  Then we can define:

	s = the number of shapes supported
	d = the number of devices supported
	f = s + d = the total number of features supported

If we expect feature requests asking for additional shapes and feature
requests asking for additional devices to both arrive at a reasonable
rate, it seems reasonable to assume that s = O(d), or equivalently that
d = O(s).  Since the number of display methods required is d * s, the
cost of implementing f features is O(f^2).  Over time it will become
increasingly difficult to add new features, until eventually the cost
of supporting additional features will become so huge that adding any
new features will become effectively impossible.


Let me map out an alternative design.  To begin with, I assume that
each device has a set of drawing operations that it accepts.  Presum-
ably all devices permit drawing individual pixels, but higher level
operations are likely to be much faster and therefore should be used
if available.  So this design has three sets which are expected to grow
over time:  the set of shapes, the set of devices, and the set of
drawing operations.

Associated with each device is a list of supported drawing operations
and the implementations of the supported operations.  Associated with
each shape is a list of display implementations.  Associated with each
display implementation is a list of drawing operations used by the
implementation.  To display a particular shape on a particular device,
you:
	1)  Get the list of operations supported by the device.
	2)  Select the first display implementation for the shape that
	    uses only those operations, and
	3)  Call the display implementation.

Display implementations are ordered by the programmer so that if there
more than one implementation could be selected by step 2, the one using
the fewest drawing operation is selected.

With this design you could still see O(f^2) display implementations,
but this is unlikely, for several reasons.  First, the larger the set
of drawing operations gets, the less likely it is that a new device will
implement drawing operations which are not already in the set.  There-
fore, the number of drawing operations is not likely to be proportional
to the number of devices.  Second, once a fair number of operations are
supported, it is likely that any new operations will be specialized
operations which are only useful with a handful of shapes.  Thus the
cost of supporting a new operation may not be proportional to the
number of shapes.  Finally, it is important to note that this design
allows you to make trade offs between development effort and performance.
For example, if you add a device which supports drawing parabola segments,
it is not necessary to write a circle display routine which uses this
drawing operation before you can start using the device.  Instead, you
can just allow some existing circle drawing routine (which uses line
segments, for example) to do the job.  So if the cost of adding new
features starts to increase, you may be able to take advantage of
increasing hardware speeds to convince your customers to accept less
efficient implementations.

This design still uses multiple dispatch for the display routine since
which display routine is called depends upon both the shape and the
device.  (Inside the display routine, single dispatch is used to call
the drawing operations.)  The difficulty is that the algorithm used to
select the display routine is application specific.  It is also subject
to change; it might prove necessary at some point to specify costs for
each drawing operation and select the minimal cost display operation.
As far as I have been able to figure out, this is true in most cases
where multiple dispatch would be useful.

Does CLOS provide any way of doing this sort of thing?  I suppose that
in LISP it wouldn't be too unreasonable to write code to generate the
dispatch table at compile time.
					Kenneth Almquist
