
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()

Armin Rigo wrote:
Hoohooo, is that! neat.
I like the idea very much! Can we adopt this for pypy? Highly elegant. Also it appears to be quite efficient. ciao - chris -- Christian Tismer :^) <mailto:tismer@stackless.com> Mission Impossible 5oftware : Have a break! Take a ride on Python's Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/ 14109 Berlin : PGP key -> http://wwwkeys.pgp.net/ work +49 30 89 09 53 34 home +49 30 802 86 56 mobile +49 173 24 18 776 PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04 whom do you want to sponsor today? http://www.stackless.com/

Hello Christian, On Thu, Feb 26, 2004 at 06:12:22PM +0100, Christian Tismer wrote:
It´s worth thinking about. There are actually variations on the idea that I´ve been playing around for other uses as well, like context-dependent methods on objects. For example, suppose that we have a class R_Int in the translator for "Python integer". This one would be pretty generic, created by the annotation analysis. Then we need to translate it, either to C or to Lisp. This would be best done with methods on R_Int like get_c_type(), define_c_variable(), etc., and the same for Lisp. It is not elegant to have all these methods added to the pretty general and translation-independent class R_Int, but it is a burden to have to use isinstance(x, R_Yyy) all the time. So we could have a "view" class with a special meta-class: class CWriter(View): pass class __view__(CWriter, R_Int): def get_c_type(self): # self is here an R_Int instance def define_c_variable(self): etc. To be used as: CWriter(x).define_c_variable() So CWriter(x) is similar to pair(x,y) in the multimethod example, with just one argument in this case: it means "a proxy object around x whose type is the one defined by the class __view__(CWriter, x.__class__)". This can have numerous usages, e.g. for the awful pypy_xxx methods that some built-in classes have (PyFrame, PyCode, etc.). A bientot, Armin.

Hello everybody,
I just found out a neat way to do simple multimethods in Python, so I
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@tunes.org> To: <pypy-dev@codespeak.net> Sent: Tuesday, February 17, 2004 10:58 PM Subject: [pypy-dev] Multimethods again thought the base

Armin Rigo wrote:
Hoohooo, is that! neat.
I like the idea very much! Can we adopt this for pypy? Highly elegant. Also it appears to be quite efficient. ciao - chris -- Christian Tismer :^) <mailto:tismer@stackless.com> Mission Impossible 5oftware : Have a break! Take a ride on Python's Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/ 14109 Berlin : PGP key -> http://wwwkeys.pgp.net/ work +49 30 89 09 53 34 home +49 30 802 86 56 mobile +49 173 24 18 776 PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04 whom do you want to sponsor today? http://www.stackless.com/

Hello Christian, On Thu, Feb 26, 2004 at 06:12:22PM +0100, Christian Tismer wrote:
It´s worth thinking about. There are actually variations on the idea that I´ve been playing around for other uses as well, like context-dependent methods on objects. For example, suppose that we have a class R_Int in the translator for "Python integer". This one would be pretty generic, created by the annotation analysis. Then we need to translate it, either to C or to Lisp. This would be best done with methods on R_Int like get_c_type(), define_c_variable(), etc., and the same for Lisp. It is not elegant to have all these methods added to the pretty general and translation-independent class R_Int, but it is a burden to have to use isinstance(x, R_Yyy) all the time. So we could have a "view" class with a special meta-class: class CWriter(View): pass class __view__(CWriter, R_Int): def get_c_type(self): # self is here an R_Int instance def define_c_variable(self): etc. To be used as: CWriter(x).define_c_variable() So CWriter(x) is similar to pair(x,y) in the multimethod example, with just one argument in this case: it means "a proxy object around x whose type is the one defined by the class __view__(CWriter, x.__class__)". This can have numerous usages, e.g. for the awful pypy_xxx methods that some built-in classes have (PyFrame, PyCode, etc.). A bientot, Armin.

Hello everybody,
I just found out a neat way to do simple multimethods in Python, so I
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@tunes.org> To: <pypy-dev@codespeak.net> Sent: Tuesday, February 17, 2004 10:58 PM Subject: [pypy-dev] Multimethods again thought the base
participants (3)
-
Armin Rigo
-
Christian Tismer
-
Günter Jantzen