On Feb 17, 12:27 pm, Simon King <simon.k...@uni-jena.de> wrote:
> Question: Do we *want* that subclasses can override it? After all, if
> they are sub-class of UniqueRepresentation, then they are supposed to
> show the unique representation behaviour---which includes that
> comparison is by identity.

I think we shouldn't go out of our way to prevent it. The "python" way
is to regulate by convention rather than enforcement. It means that
people who know what they are doing (or are willing to void their
warranty) are still capable of deviating from the convention.

> That's why I suggest to separate the two features of
> UniqueRepresentation: Cache on the one hand, comparison by identity on
> the other hand. If one wants another hash or another comparison, then
> one should inherit from the to-be-created CachedRepresentation, and not
> from UniqueRepresentation.

Yes, having code express intent is nice. However, if effectively the
two are identical in their implementation perhaps one shouldn't
bother.

> I think yes. But what happens if you want "a < b" work in a specific
> way? You would probably override __cmp__ (at least this is what many
> classes do), and if one overrides __cmp__ without providing __hash__,
> then you can't use it in a dictionary.

If I understand correctly, Python has grown both __cmp__ and
__richcmp__ for backwards compatibility, not by design. (__cmp__ was
slated for removal for 3.0 at some point). That's why __richcmp__ (the
newer, preferred method as far as I can tell) takes precedence over
__cmp__. So on a legacy-free platform, I think the answer is: Those
users should implement their own __richcmp__ and return NotImplemented
for "==" and "!=" if they want to keep those as before. Python's funny
rules about how inheritance of hash and comparison are linked may mean
that that doesn't actually work:

"""
This field [tp_compare] is inherited by subtypes together with
tp_richcompare and tp_hash: a subtypes inherits all three of
tp_compare, tp_richcompare, and tp_hash when the subtype’s tp_compare,
tp_richcompare, and tp_hash are all NULL.
"""

from object.__hash__ (Python data model documentation):

"""
If a class does not define a __cmp__() or __eq__() method it should
not define a __hash__() operation either; if it defines __cmp__() or
__eq__() but not __hash__(), its instances will not be usable in
hashed collections. If a class defines mutable objects and implements
a __cmp__() or __eq__() method, it should not implement __hash__(),
since hashable collection implementations require that a object’s hash
value is immutable (if the object’s hash value changes, it will be in
the wrong hash bucket).

User-defined classes have __cmp__() and __hash__() methods by default;
with them, all objects compare unequal (except with themselves) and
x.__hash__() returns id(x).
"""

suggests that for python subclassing, providing any rich method but
__eq__ should be fine. That means that python-level subclassing
already plays some interesting games: If just "__lt__" is provided,
the "__richcmp__" slot needs to be filled, but "__hash__" is still
inherited.

I don't think it's the job of UniqueRepresentation to fix
inconveniences in the python inheritance model. In fact, doing so
makes using it more complicated because people have to remember it
works differently from how python usually works.

Anyway, to get the desired behaviour, I think you could just set
tp_hash and tp_richcmp upon __cinit__. Avoiding messing with
"__classcall__" when not strictly necessary seems preferable to me any
time.

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To post to this group, send email to sage-devel@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-devel?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to