[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