I'm experimenting with a system implementing a perfectly sound
double-dispatch, even in the face of multiple inheritance, bypassing
Python's byzantine and subtly incorrect rules. It is based on a callable
binary_operation object that stores implementations for pairs of types.
When it is called, it finds the implementation corresponding to the most
derived pair of types or raises an error in case of ambiguity. 

Concretely, with the following definitions:

power = binary_operation()

@power.define(Expr, Expr) # same as power[Expr, Expr] = _pow_base
def _pow_base(x, y):
    return Pow(x, y)

@power.define(Expr, Zero)
def _pow_Expr_Zero(x, zero):
    return S.One

@power.define(Zero, Expr)
def _pow_Zero_Expr(zero, x):
    return S.Zero

then:
        * power(Symbol('x'), Integer(2)) calls Pow.
        * power(Symbol('x'), S.Zero) returns S.one directly.
        * power(S.Zero, S.Zero) raises an error, because there are two
        conflicting definitions. You can fix this with 
        power[Zero, Zero] = power[Expr, Zero].

Now, if we plug this function into Expr.__pow__, we'll be able to define
the behaviour of '**' in a modular way, provided we also turn Pow into
an inert object (i.e. with the behaviour currently corresponding to
evaluate=False). I've started coding in that direction in
https://github.com/rlamy/sympy/tree/binop It works (except for some
problems with integral transforms) but it's a bit slow as the overhead
of double-dispatch is significant.

What do you think?






-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sympy?hl=en.

Reply via email to