[Python-Dev] Multimethods (quel horreur?)

Samuele Pedroni pedroni@inf.ethz.ch
Fri, 16 Aug 2002 15:04:15 +0200

[f,g,... are functions ;  T1,T2,T3 are type tuples a.k.a multi-method
signatures, T1<T2 means the corresponding elements
are "subtypes" ]

1. if I see things correctly, you are really fiddling with a multi-method
M = { (f,T1), (g,T2), ... }from a library

only if you do e.g.

add(M,(h,T3))  with T3==T2 (*) or T1<T3<T2.

[Things one typically does not do without thinking

[Btw up to (*), missing a module or calling
a generic function before all modules are loaded,
load order does not count.]

If T3 is < or incomparable with all the signatures in M,
is not fiddling. Incomparable can mean dispatch ambiguities
but that's a different issue.

import lib

class Sub(lib.Class1):

class New:

addmethod lib.gf(x: Sub,y: Sub):

addmethod lib.meth(arg: Sub):

is no different than defining new classes and subclassing and
overriding methods. Also the kind of resulting program
logic scattering is not that different under normal usage.

2. Dispatch ambiguities: the more predictable the rule
the better, the best-fit of multimethod does not match
such a criterion, see my previous postings.

Rules for CLOS:
(NB things are eminently configurable in CLOS)

Rules for Dylan:

The class predecende list is the same notion
as Python 2.2 mro.

See my posted code for the idea of redispatching
on forced types, which seems to me reasonably Pythonic
and allows OTOH to choose a very strict approach
in face of ambiguity because there's anyway a user
controllable escape.

My opinion: left-to-right and refuse ambiguity
are depending on the generic function both
reasonable approaches.

3. IMO documentation, doc strings, and introspection
should be enough to tell generic functions apart.
The proposed notation or whatever should be at most
 just syntax sugar:

(a,b,c).f(d) === f(a,b,c,d) in general.

Generic functions should be first-class object
that can be passed around and used everywhere
functions can be. Already today f(a,b) 
can invoke a function, a callable instance
(maybe implemeting some multimethod logic given that
one can write multimethod support in pure Python),
a bound method ...

4.  AFAIK multimethods where invented in environments
with code developed and defined in memory incrementally
and libraries loaded, that means that through introspection
one could list the methods of a generic functions and jump
to the various definitions points, and warnings could
be issued for redefinitions and such (see 1.).
For more static approaches to introspection 
syntactic sugar would be probably useful: 

defgeneric addmethod vs. f.add(...)

Of course a Python impl could also
optionally emit warnings etc, this requiring
the good practice to load library code before
user code, and being maximally useful in
an incremental environment.

5. It is true that once you have multimethods you have
the choice:

class C: 
  def meth(...): ...


class C: ...

defgeneric meth

addmethod meth(obj: C): ...

6. It is true that generic functions kind of add
a new degree of freedom to the modularity problem

7. The less disruptive and convenient usage for 
multimethods is to get something like overloading:

defgeneric f

addmethod f(x: int): ...

addmethod f(s: str): ...


class A:
  defgenericmethod meth

  addmethodmethod meth(self,x: int): ...

  addmethodmethod meth(self,s: str): ...

class B(A):
  defgenericmethod meth 
  # in case of no match it is supposed to redispatch
  # to the superclasses

  addmethodmethod f(self,x: int): ...

Syntax and semantics are just hypothetical

-- * --

For an overview on CLOS with some
words about generic functions vs. message passing
and modularity issues:

The Common Lisp Object System: An Overview 
Linda G. DeMichiel and Richard P. Gabriel


[Unrelated: http://www.dreamsongs.com is the personal site of
Richard P. Gabriel, some interesting writings there on

For the description of a large generic function
based system:

Common Lisp Interface Manager 
CLIM II Specification


[I said large.]

I'm not claiming to be an expert on multi-methods,
just I have played with the notion, read about,
and thought of it before this discussion.


PS: this is my input together with what I have already
posted, if something is unclear please ask.