The Artima Developer Community
Sponsored Link

Python Buzz Forum
More on Multimethods

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Ian Bicking

Posts: 900
Nickname: ianb
Registered: Apr, 2003

Ian Bicking is a freelance programmer
More on Multimethods Posted: Apr 16, 2005 3:07 PM
Reply to this message Reply

This post originated from an RSS feed registered with Python Buzz by Ian Bicking.
Original Post: More on Multimethods
Feed Title: Ian Bicking
Feed URL: http://www.ianbicking.org/feeds/atom.xml
Feed Description: Thoughts on Python and Programming.
Latest Python Buzz Posts
Latest Python Buzz Posts by Ian Bicking
Latest Posts From Ian Bicking

Advertisement

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

Read: More on Multimethods

Topic: What Really Makes Rails Work Previous Topic   Next Topic Topic: I590 slides available

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use