Discussion: new operators for numerical computation

Eric Lorenzo zo at angband.org
Mon Jul 24 21:48:19 EDT 2000


"Neil Hodgson" <neilh at scintilla.org> writes:
>    I had a look at Dylan a few years ago and multimethods look good for some
> areas but you also lose the encapsulating aspect of normal OO. The
> functionality for a class isn't nicely tied up in one bundle but is
> federated over a wide and extensible area.

I'd say that with binary operators like those we're discussing here,
the operation isn't necessarily more closely tied to one of the input
types than the other, so it doesn't really make sense to make the
operation a method on only one of those types.  So yeah, you're
reducing encapsulation a bit with multi-methods, but in my view,
that's okay, because arbitrarily encapsulating the addition of two
objects into the class of whichever happens to be on the left isn't
really appropriate, anyways.

And the lack of multimethods leads to some ugliness, as well.  Here's
an example: I've got two classes, point and vector.  point+vector,
vector+point, and vector+vector are all legal, but point+point isn't.

Without multimethods, I do:

    class point:
        ...
        def __add__(x):
            if type(x) == InstanceType and isinstance(x, vector):
                # do point+vector here
            else:
                # throw a TypeError

    class vector:
        ...
        def __add__(x):
            if type(x) == InstanceType:
                if isinstance(x, point):
                    # do vector+point here
                elif isinstance(x, vector):
                    # do vector+vector here
                else:
                    # throw a TypeError
            else:
                # throw a TypeError



With them, I do:

    class point:
        ...

    class vector:
        ...


    multimethod __add__(p:point, v:vector):
        # do point+vector here

    multimethod __add__(v1:vector, v2:vector):
        # do vector+vector here

    multimethod __add__(v:vector, p:point):
        # do vector+point here.


Now, to my eye, the latter is far more elegant and matches what's
happening conceptually much more closely, since it treats the type of
each of the two arguments as if they are of equal importance and uses
the same mechanism to deal with both.  In contrast, in the first
approach, we use implicit type checking to deal with the type of the
lefthand argument, and explicit type checking (and some attendant
error handling) to deal with that of the right.  The resulting code is
considerably less legible, to my eye.

Because C++ takes into account the type of all parameters (and not
just that of the implicit first parameter of method calls (i.e. self),
as Python does) when choosing what function body to dispatch, I was
able to do something very similar to the latter when implementing a
ray tracer in that language.  I'm doing work in a related problem
domain in Python now, and am having to resort to (IMO) rather ugly
code like the first block.  This is the one case in which I find C++
to be cleaner and more elegant than Python.

Eric



More information about the Python-list mailing list