declaring multimethods [Was: Re: PEP 318]

Skip Montanaro skip at pobox.com
Wed Mar 24 10:32:19 EST 2004


    Michele> Please take what I posted just as an idea (it is not even my
    Michele> idea!), not as an implementation proposal.  I don't have an
    Michele> implementation, but I am pretty much convinced that it is
    Michele> possible and not that hard.

    ...

    Michele> Just to support your point that the decorator idea is a Pandora
    Michele> box, and we can extract anything from it ;)

Perhaps, but the box is already there.  All the decorator syntax does is
maybe make it a bit easier to pry off the lid. ;-)

Still, I'd like to follow this thread just a little further, mostly just to
see where it goes.  I will assume the presence of PEP 318 decorators.  We
have a Matrix(?) class which we want to multiply by various other object
types:

    class multimethod [singleton]:
        def __init__(self):
            self.methods = {}

        def __call__(self, t1, t2):
            def decorator(f):
                ... here's where the work gets done ...
                return something_like_f
            return decorator

    class Matrix:
        def __mul__(self,other) [multimethod(Matrix,Matrix)]:
            ...
            return result

        def __mul__(self,other) [multimethod(Matrix,Vector)]:
            ...
            return result

        def __mul__(self,other) [multimethod(Matrix,Scalar)]:
            ...
            return result

Using the proposed PEP 318 semantics, at the time decorator(<function>) is
called, it will be passed a function object but "__mul__" will not have been
seen yet.  However, the function object's func_name field should have been
filled in.  That should give it enough information to build a new function
object.  It knows the proposed types from t1 and t2 in the enclosing
method's scope and it knows the function's name, so it has enough for a
C++-style signature.  It can save a list of tuples consisting of the
function object and t2 in self.methods keyed by the name and t1 (t1 must
always be the class).  Hmmm... t1 presents a problem since at the time
multimethod(Matrix,Matrix) is called there is no Matrix class available (it
hasn't been bound yet).  You'd have to fudge that and use strings as the
type names.  That presents another problem.  Classes, unlike functions,
don't have name attributes, so mapping the names passed to multimethod() to
classes is problematic.  You could punt and decorate the class:

    class Matrix [attributes(_name="Matrix")]:
        ...

but then you're naming the class twice.

It certainly seems doable, but the end result doesn't seem all that pretty.
I think it would look sort of like:

    class Matrix [attributes(_name="Matrix")]:
        def __mul__(self,other) [multimethod("Matrix","Matrix")]:
            ...
            return result

        def __mul__(self,other) [multimethod("Matrix","Vector")]:
            ...
            return result

        def __mul__(self,other) [multimethod("Matrix","Scalar")]:
            ...
            return result

Skip




More information about the Python-list mailing list