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()
participants (3)
-
Armin Rigo
-
Christian Tismer
-
Günter Jantzen