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.