Multiple dispatch again

David Mertz mertz at gnosis.cx
Thu Jan 2 08:01:42 CET 2003


I've got to thinking about multimethods/multiple dispatch lately.  I
wonder if Pythonistas have some futher opinions on the use of these.
Actually, part of it is that I'd -really- like to better understand use
cases for multiple dispatch.  As a trick, I can see it has a certain
elegance, but little rock/paper/scissors toys are not, finally,
compelling.

An inspiration for the code I am about to mention is simple and
beautiful code posted a bit over a month ago by Tim Hochberg.  I played
with that, and enhanced it fairly greatly at:

    http://www.gnosis.cx/secret/multimethods.py

I welcome comments of any sort on the code.

There are a few things that I had particularly in mind.  In reading
about Dylan, I found that it has a method named 'next-method( )' to
propogate dispatch from the closest match to more distant ones.  You can
control whether you want this to happen by including that method, or
not.  Take a look at:

    http://www.tpk.net/~ekidd/dylan/multiple-dispatch.html

In my code, I added the facility to propogate dispatch.  Using the
simple example that was a topic of conversation here 6 weeks ago, you
can make a call like:

    beats.add_rule((Fire,Thing), firepower, next_meth=AT_END)

I give you options to propogate dispatch either before or after the code
within the current method execution.

As well, I decided to make dispatch resolution order configurable.
Hochberg's example was perhaps naive in fixing resolution order
according to definition order.  That seems a little fussier than I would
want.  So I made that configurable as well, and provide four sample
resolution functions.  Two are naively definition-order based (either
forward or reversed).  But two others are perhaps better candidates:
'lexicographic_mro()' and 'weighted_mro()'.  If I understand correctly
(which I may not), the first follows Dylan, the second follows Damian
Conway' Class::Multimethods.  I would be interested to understand other
examples, particularly CLOS.  I have little intuition about what is the
"right" answer.

Since I allow propogated dispatch, I had to decide what to do with
results from the function calls.  I decided to accumulate all returned
values into a list, and let the user pick what they want.  So for
example:

    <fire, fire>      ['Fire always wins!', 'Fire always wins!', 0]

But for a non-propogating rule, the list has a single member:

    <rock, scissors>  [1]

If you stick to either 'SKIP' or 'AT_END' propogation, you can count on
index 0 of the return being the most specific function's value.  Or if
conversely, you like 'AT_START', you can use index -1.  If you mix the
two styles, it could become complicated to find relevant return values.

Yours, David...

--
Keeping medicines from the bloodstreams of the sick; food from the bellies
of the hungry; books from the hands of the uneducated; technology from the
underdeveloped; and putting advocates of freedom in prisons.  Intellectual
property is to the 21st century what the slave trade was to the 16th.





More information about the Python-list mailing list