[pypy-dev] Multimethods again

Günter Jantzen nc-jantzegu at netcologne.de
Sun Mar 7 20:18:28 CET 2004


Hello Armin,

maybe it is already well known, but recently I saw that David Mertz
contributed an article about
(and an implementation of)  multimethods in his famous column "Charming
Python" at
http://www-106.ibm.com/developerworks/linux/library/l-pydisp.html
about one year ago. His work also covers preference policies for unambigious
method resolution

Best regards
Günter


----- Original Message -----
From: "Armin Rigo" <arigo at tunes.org>
To: <pypy-dev at codespeak.net>
Sent: Tuesday, February 17, 2004 10:58 PM
Subject: [pypy-dev] Multimethods again


> Hello everybody,
>
> I just found out a neat way to do simple multimethods in Python, so I
thought
> I'd share it with you :-)
>
> The following is only for dispatching over two arguments.  The idea is to
use
> a pair(a,b) object that is just like a tuple (a,b), but with methods.  Any
> (regular Python) method that you put in the class of pair(a,b) works like
a
> multimethod dispatching on both a and b.  The metaclass hack is only a
> syntactic convenience.
>
> I don't know if this is relevant to PyPy.  It's probably one of the
shortest
> multimethod implementations for Python, whereas PyPy's is probably one of
the
> longest :-)
>
> Armin
>
> # ______________________________________________
>
> class extendabletype(type):
>     """A type with a syntax trick: 'class __extend__(t)' actually extends
>     the definition of 't' instead of creating a new subclass."""
>
>     def __new__(cls, name, bases, dict):
>         if name == '__extend__':
>             return bases[0]   # return existing base
>         else:
>             return type.__new__(cls, name, bases, dict)
>
>     def __init__(self, name, bases, dict):
>         if name == '__extend__':
>             for key, value in dict.items():
>                 setattr(self, key, value)
>
>
> def pair(a, b):
>     """Return a pair object."""
>     tp = typeofpair(a.__class__, b.__class__)
>     return tp((a, b))   # tp is a subclass of tuple
>
> pairtypecache = {}
>
> def typeofpair(cls1, cls2):
>     """type(pair(a,b)) is typeofpair(a.__class__, b.__class__)."""
>     try:
>         pair = pairtypecache[cls1, cls2]
>     except KeyError:
>         name = 'typeofpair(%s, %s)' % (cls1.__name__, cls2.__name__)
>         bases1 = [typeofpair(base1, cls2) for base1 in cls1.__bases__]
>         bases2 = [typeofpair(cls1, base2) for base2 in cls2.__bases__]
>         bases = tuple(bases1 + bases2) or (tuple,)  # 'tuple': ultimate
base
>         pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {})
>     return pair
>
> # ____________________________________________________________
>
>
> class A(object):
>     pass
>
> class B(object):
>     pass
>
> class C(A):
>     pass
>
> class D(B):
>     pass
>
> a = A()
> b = B()
> c = C()
> d = D()
> assert isinstance(pair(a,b), typeofpair(A, B))
>
>
> class __extend__(typeofpair(A, B)):
>
>     def add((a, b)):
>         print "a+b"
>
>     def sub((a, b)):
>         print "a-b"
>
>
> class __extend__(typeofpair(C, B)):
>
>     def add((c, b)):
>         print "c+b"
>
>
> # alternate less magic syntax
> def sub((a, d)):
>     print "a-d"
> typeofpair(A, D).sub = sub
>
>
> pair(a,b).add()
> pair(a,b).sub()
> pair(c,d).add()
> pair(c,d).sub()
>
> _______________________________________________
> pypy-dev at codespeak.net
> http://codespeak.net/mailman/listinfo/pypy-dev



More information about the Pypy-dev mailing list