David H,

Hi -- I'm concerned because I think the __add__, etc., architecture that  
you
guys came up with (as of now) prevents implementation of any derived  
class's
arithmetic in Python.   You do have an _add_sibling_cdef in the base class
that tries to deal with this problem, but it only works if the Python class
derives directly from RingElement.  If the derivation looks like this:

                RingElement

                  Integer

                My Python Class

then your current solution doesn't work.

More precisely, suppose somebody makes a class MyInteger:

   class MyInteger(Integer)

and they want to define their own version of "+", so that if x and y are
of type MyInteger, then x+y is also.  Since MyInteger is defined in Python,
there is no way to overload _add_sibling_cdef, which is a cdef.   The user
could of course overload __add__, but then their type doesn't obey SAGE's
coercion rules.

If MyInteger defines a Python method _add_sibling,

   def _add_sibling(self, right):
       ...

does that mean in the base class __add__ method, we're going to have
to check for _add_sibling every time we do an add?  If so, this could
end up being slower than just making everything a Python def method.

Perhaps there is a fast way to tell whether a class is a Python class or a  
Pyrex
class (say in the base class __add__ method), and always call  
_add_sibling_cdef
if it's a Pyrex class and _add_sibling if it's a Python class.   There  
probably
is, because, e.g., Pyrex classes and Python classes print differently; one  
prints
as <type ...> and the other as <class ...>.  I've been looking at the  
Python/C
API for a few minutes though and I haven't figured out a fast way to  
distinguish
these two.

NOTE.  Also, you (obviously) can't just over-ride _add_sibling_cdef
with some Python code:

sage: class myint(Integer):
...    def _add_sibling_cdef(self, x):
...        print "hello world"
sage: a = myint(1); b = myint(2)
sage: type(a + b)
<type 'sage.rings.integer.Integer'>

Another possible (but confusing) option is to require that Python classes  
that
derive from builtin SAGE classes multiply inherit.  E.g., the following  
works:

sage: class python_arith:
...    def __add__(self, x):
...         return self._add_sibling(x)

sage: class myint(python_arith, Integer):
...    def _add_sibling(self, x):
...        print "python _add_sibling"
...        return myint(0)
...    def _add_(self, x):
...        print "_add_"

sage: a = myint(1); b = myint(2)

sage: type(a+b)
python _add_sibling
<class '__main__.myint'>

-------

But it is potentially *very* confusing to be forced to multiply derive
whenever inheriting from SAGE builtin types.   Plus I'll never remember
the name of the other class I have to inherit from.

Even if we can determine whether a class is defined in Pyrex instead
of Python,  another potential confusion would be if the user moves a
Python class to Pyrex and forgets to change from _add_sibling to
_add_sibling_cdef.

By the way, this stuff you guys did " x = <Integer> PY_NEW(Integer)"
is impressively fast!  From that I get a factor of 5 speed up in
some tests I'm doing.

-- William

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-devel@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/
-~----------~----~----~----~------~----~------~--~---

Reply via email to