# More on Multimethods

I think Guide is thinking about typing and whatnot a lot lately, now with a post one multimethods, which mostly the same as double-dispatch. I.e., you choose a function implementation based on the type of the arguments.

However, Guido uses a global registry of functions by name. I like Phillip's technique for generic functions, which is to give these a functions a richer interface that includes a decorator. Here's an example of Guido's code converted to that:

```@multimethod
def div(a, b):
"div a by b"
return a / b
class rational(object):
def __init__(self, num, denom):
self.num, self.denom = num, denom
def __repr__(self):
return '%s/%s' % (self.num, self.denom)
@div.types(rational, int)
def div_rat_int(r, i):
return rational(r.num, r.denom*i)
@div.types(int, rational)
def div_int_rat(i, r):
return rational(r.denom * i, r.num)
@div.types(rational, float)
def div_rat_float(r, f):
return r.num / (r.denom*f)
@div.types(float, rational)
def div_float_rat(f, r):
return f * r.denom / r.num
@div.types(rational, rational)
def div_rat_rat(r1, r2):
return rational(r1.num * r2.denom, r1.denom * r2.num)
```

Here's how it looks:

```>>> half = rational(1, 2)
>>> half
1/2
>>> third = rational(1, 3)
>>> div(half, third)
3/2
>>> div(half, 2)
1/4
>>> div(half, 0.5)
1.0
>>> div(1, 2)
0
>>> div(1, half)
2/1
```

And here's the implementation (it's actually simpler than Guido's):

```class multimethod(object):
def __init__(self, default):
self.default = default
self.name = default.__name__
self.__doc__ = default.__doc__
self.typemap = {}
def __call__(self, *args):
types = tuple(arg.__class__ for arg in args) # a generator expression!
function = self.typemap.get(types, self.default)
return function(*args)
def types(self, *types):
def decorator(func):
if types in self.typemap:
raise TypeError("duplicate registration")
self.typemap[types] = func
if func.__name__ == self.name:
# to avoid confusion by overwriting the multimethod function
return self
else:
return func
return decorator
```

The module is located online at http://svn.colorstudy.com/home/ianb/recipes/multimethod.py

Update: some people have mistakenly called this implementation a generic function, or a reimplementation as a generic function. It's not generic (aka predicate-dispatch) functions at all -- those are much more general (and powerful), and this version is just a slightly different factoring of Guido's code. Thankfully Bob Ippolito does it right and shows how to implement multimethods with generic functions.

Created 01 Apr '05
Modified 04 Apr '05

```if sys._getframe(1).f_locals.get(func.__name__) is self: