[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
twice]
[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:
http://www.lispworks.com/reference/HyperSpec/Body/07_ffab.htm
(NB things are eminently configurable in CLOS)
Rules for Dylan:
http://www.gwydiondylan.org/drm/drm_50.htm
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(...): ...
vs.
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
space.
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): ...
OR
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
http://www.dreamsongs.com/NewFiles/ECOOP.pdf
[Unrelated: http://www.dreamsongs.com is the personal site of
Richard P. Gabriel, some interesting writings there on
software]
For the description of a large generic function
based system:
Common Lisp Interface Manager
CLIM II Specification
http://www.mikemac.com/mike/clim/cover.html
[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.
regards.
PS: this is my input together with what I have already
posted, if something is unclear please ask.