-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Refactor objset #765
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor objset #765
Conversation
| where | ||
| Self: Sized, | ||
| { | ||
| fn get_elements(&self) -> HashMap<u64, PyObjectRef>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we definitely don't want to copy the entire map just to eg check its size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same as the current implementation. I would prefer not changing the functionality of the code in this PR to make it easier to review. This is a big diff and I think improving in a different PR will be better.
I did add __iter__ to frozenset but used the same code as already existed in set.
|
Sharing functions between python classes with a trait doesn't really seem like the right approach to me, because now the structure of the rust code does not directly map to that of the python code it represents. Also I don't think this meshes super well with the proc-macro approach to class definition being developed in #764. I understand the desire to have them share code, but imo duplication is far cheaper than the wrong abstraction. |
Side note, I asked about it in comment #764 (review) and @coolreader18 thinks it can work.
Now we're going back to my topic from that PR - I do think they don't necessarily should map anyway. However, I do agree with your last statement that this deduplication may possibly complicate code in the long run, while not giving proportional advantages. We can also see that in #770 (comment) - we're again figuring out reference passing, while recent refactors let us drop |
You are currently sharing code between the types just without the trait that allow you to use the new arg style. My opinion is that the code is more readable this way but I am biased.
I understand your concern and will try solving the problems that were pointed about the copy.
I don't think this adds a level of abstraction to the implementation. Specifically talking about |
|
I'd be interested in an answer about it (share a trait between frozentset and set) because I was on the point to do it for bytes and bytearray. |
|
This feels like the wrong abstraction to me too. As does the existing code, I think the new code is probably an improvement. Everything feels a bit inside out. It feels to me like we want: a rust set implementation that provides the basic interface for sets in pure rust, and then some repetitive simple wrappers that unwrap/wrap from both types. I think it would be simpler but more repetitive. (This is hard/be sure it makes sense without trying it.) |
I am not sure I understand what your suggestion. Are the wrappers written in python? |
|
@cthulahoops is this something like what you were suggesting? I see this "Inner" pattern in a lot of rust code. struct PySet {
inner: RefCell<PySetInner>,
}
impl PySetRef {
fn some_set_method(self) {
self.inner.borrow().some_set_method()
}
}struct PyFrozenSet {
inner: PySetInner,
}
impl PySetRef {
fn some_set_method(self) {
self.inner.some_set_method()
}
}struct PySetInner {
// actual set represetation
}
impl PySetInner {
fn some_set_method(&self) {
// the real implementation
}
} |
|
This look like a nice way to go @OddCoincidence. I have a few points:
|
impl PySetInner {
fn update(&mut self, other: PyIterable) {
// do it
}
}
impl PySetRef {
fn update(self, other: PyIterable) {
self.inner.borrow_mut().update(other)
}
}
impl PyFrozenSetRef {
// no update method
}
No, PySetInner would never reference PySet or PyFrozenSet, it would operate in terms of itself. impl PySetInner {
fn union(&self, other: &Self) -> PySetInner {
// do it
}
}
impl PySetRef {
fn union(self, other: PySetRef) -> PySet {
self.inner.borrow().union(&other.inner).into() // via appropriate From impl
}
}
impl PyFrozenSetRef {
fn union(self, other: PySetRef) -> PyFrozenSet {
self.inner.union(&other.inner).into() // via appropriate From impl
}
}
I am 100% okay with this. They are different types, the methods should be explicitly specified for each one. |
|
Sorry for not being clearer in my last rushed post. Thanks, @OddCoincidence, that's exactly what I was thinking. |
|
(I'm not sure I like the name |
|
Why does this use HashMap instead of Hashset ? |
|
So that we can store arbitrary hashable objects in sets. It's a map of hash value to |
|
I will start working on |
How do we handle hash collisions? |
We don't. (I tried to work out the answer to this myself earlier.) I guess once we have proper dicts working we can use the same approach to fix sets. |
I have started working on the implementation and I seem to have the same problems as before. The |
Ah, I didn't consider this. Yeah, using
I think this will help too. @cthulahoops Are you okay with me merging #774 or do you still have concerns with it? |
|
I thought Pysetref was mandatory since user could call union with any type, not only set or frozenset |
|
Actually, @palaviv for |
We might also be able to implement sets as dicts where the value is |
You mostly convinced me. I'm okay with you merging that. |
|
Was implemented using inner in #785. |
I tried to make the code sharing between
setandfrozensetmore nice. I created a shared traitSetProtocolthat implements all the shared function. I also moved thesetonly functions to the new format.I was not sure how to move the
newimplementation toSetProtocolif anyone has suggestions?