Note: August 2008: Much of this material is out of date. We are working on a revised version.
Let
and
be Sage parent structures, e.g., groups, rings, point
sets, etc.
_coerce_:
Suppose a _coerce_ map S._coerce_(x), where
def _coerce_(self, x):
....
R.category() must be a subcategory of S.category()
or conversely.
_coerce_ must
define a morphism in the bigger category; in particular, the map must be
defined on all of
_coerce_ is defined in both direction, i.e.,
R is S is True, then
_coerce_ must be the identity map. Here, by R is S
being True, we meant that
T._coerce_(S._coerce_(x)) == T._coerce_() must be True.
(When you implement a
new ring, this means you should look at what rings coerce to the
rings that coerce to your ring, and make sure they also coerce to
your ring.)
R._coerce_(x) is defined, then R(x) (i.e.,
R.__call__(x)) must return the same thing, i.e.,
R.__call__(x) == R._coerce_(x) must be True. (We do not
require that the same Python object is returned, just an equal
object.)
_coerce_ should send generators to generators
when this makes sense. This is only a convention, and can be
violated when it isn't sensible, e.g., the map
In implementing _coerce_, we are making a fixed choice of
identifications and inclusions throughout Sage that follow the above
rules. E.g., embeddings of finite fields via Conway polynomials, or
inclusions of extensions of number fields, fit into this structure, as
does the inclusion
and the surjection
. The function _coerce_ does not have to be
``canonical'' in a precisely defined mathematical sense.
__call__:
If you write __call__ method of __call__ is never called implicitly by binary operators.
If __call__ must return
a new copy of ZZ.__call__(x) is defined but
ZZ.__coerce__(x) is not.
__add__, __mul__, ...:: When
doing a binary operation, if the parents are not identical (in the
sense of is ), determine if precisely one _coerce_ map is defined; if so, apply it and do the arithmetic
operation. If both are defined, the parents are canonically
isomorphic, so use the left one. If neither are defined, raise a
TypeError. (Whether or not there is a coerce map between objects
should be cached for efficiency.)
__cmp__: R == S by definition
means that _coerce_ is defined in both directions. Roughly
speaking this means that
__cmp__:
If the parents aren't identical, test if
precisely one _coerce_ map is defined -- if so, return __cmp__
after applying the coerce. If both coercions are defined, compute
both __cmp__'s (in both __cmp__ never raises an exception). If no _coerce_ is
defined return
__contains__:
x in R should be true if and only if R._coerce_(x) would not
raise a TypeError.
See About this document... for information on suggesting changes.