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.