On Feb 17, 3:25 pm, Simon King <simon.k...@uni-jena.de> wrote:

> However, subclasses forget everything about the hash:
>   sage: class Bar(Foo):
>   ....:     pass
>   ....:
>   sage: b = Bar()
>   sage: hash(b) == id(b)
>   False
>   sage: hash(b) == id(b) >> 4
>   True

OK, I think I've found the problem. I think cython people can comment
on this. Consider the following example:

-------------------[cython code]-----------------------------
cdef extern from "object.h":
    ctypedef struct RichPyTypeObject "PyTypeObject":
        void * tp_hash

cdef long myhash(void * v):
    return <long>v

cdef class MyHash(object):
    def __hash__(self):
        return 0
    pass

(<RichPyTypeObject *>MyHash).tp_hash = &myhash
---------------------------------------------------------

For the most part this seems to work:

sage: a=MyHash()
sage: hash(a) == id(a)
True

However, indeed as you describe:

sage: class B(MyHash): pass
sage: b=B()
sage: hash(b)
0

The only reason I can think of for inheritance not to pick up on the
changed tp_hash field is that PyType_Ready gets called on the data
structure formed for MyHash before we get a chance to change the
tp_hash field. Apparently PyType_Ready saves or copies some things
that get used for inheritance later.
Inserting the right pointer (i.e., &myhash rather than
&MyHash.__hash__) would be trivial if we were to get to process/edit
the resulting ".c" file, but it seems impossible in cython at the
moment.

Indeed, we have

sage: MyHash.__dict__["__hash__"](h)
0
sage: print MyHash.__hash__(h)
0
sage: h.__hash__()
0

In other words, scribbling over tp_hash after PyType_Ready has been
called makes for an imperfect hash override. You'd also need to change
the __hash__ entry on in the MyHash dictproxy (which you can't!)

This also affects the __classcall__ hack you proposed. You'll see
there as well that hash(a) and a.__hash__() diverge, which we can't
afford to happen.

The quickest solution is to write UniqueRepresentation as an extension
class *in C*. Then you can insert your superquick hash function into
tp_hash before calling PyType_Ready.

-- 
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