Skip to content

Conversation

@Ten0
Copy link

@Ten0 Ten0 commented Nov 30, 2019

Resolves #25
Resolves #26

What it does:

  • BTreeMultiSet implementation
  • Specialize Iter for performance
  • Fix doc links

Due to GATs not being available in rust yet the MultiSet could not be generic on both types of map (could not create the Iter associated type because it is generic on a lifetime). In order to avoid code duplication, the code for the BTreeMultiset is generated at build time through a build.rs script, using simple replacements from the hash_multiset file.

The iterator I was able to factor however, so the specializations are only here once.

This is non semver-compatible due to the Iter type being more generic.

@Ten0 Ten0 changed the title BTreeMultiset BTreeMultiset + iter specializations Nov 30, 2019
@Ten0 Ten0 force-pushed the btree-multiset branch 2 times, most recently from 1ae0269 to 7f86640 Compare December 1, 2019 00:08
Ten0 added 2 commits December 1, 2019 01:22
Only nth could be optimized further, feel free to implement it :)
@mashedcode
Copy link
Collaborator

Doing a quick diff hash_multiset.rs btree_multiset.rs. Everything in both files is the same except that BTreeMultiSet is used instead of HashMultiSet.
Which means whenever any change is made in the future it'll have to be made in both files. Wouldn't it be better to use a generic parameter for HashMultiSet instead to avoid code duplication?

@Ten0
Copy link
Author

Ten0 commented Dec 1, 2019

If we could that would indeed be better but as I mentioned above unfortunately we need GATs to be able to output the iterator when making the MultiSet generic, which we can't have at the moment.

I've also experimented with a macro version (one liner for each sub-map) but it breaks the documentation and doesn't feel very clean.

@mashedcode
Copy link
Collaborator

Another approach if you'd like to avoid using macros is a build script that does a simple search and replace which produces the second file which should be in gitignore. If the docs are run after the build script it should even produce duplicate docs.

Copy link
Collaborator

@mashedcode mashedcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job on the build.rs script.

Please remove the btree_multiset.rs file from 567aadb with a rebase.
I'd prefer it even more if you could split this PR into two separate ones. One for BTreeMultiset and one for the iterator stuff. But I guess it's fine like this.

@Ten0
Copy link
Author

Ten0 commented Jan 6, 2020

Please remove the btree_multiset.rs file from 567aadb

I agree it would hurt in the general history but I'd rather keep the PR history easily accessible along the discussion, so I think we should just squash and merge it.

@Ten0
Copy link
Author

Ten0 commented Feb 22, 2020

Up

Copy link
Collaborator

@mashedcode mashedcode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for addressing the review comments and adding test cases for the iterator!!

}
self.len -= 1;
Some(key)
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clippy: this else { if .. } block can be collapsed to else if.

}
self.len -= 1;
Some(key)
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clippy: this else { if .. } block can be collapsed to else if.

+ BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
+ Clone,
<IterItem as BitXor>::Output:
BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems unnecessary to abstract this much and create so many single use functions. I wrote-up an example of a more specific implementation. (I took the freedom to use a macro for check_specialized.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comes from an implementation I had originally written for itertools, where I had several different iterators to test, so the functions were not single use. I just reused the same. ^^
Tbh, I hate writing tests, but I'm absolutely open to use whichever test implementation you prefer. :)

Iter: Iterator<Item = IterItem> + Clone + 'a,
{
check_specialized(it, |mut i| {
let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why since x ^ x ^ x == x? How about Default instead? Or even better yet 0i32?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That minimizes the amount of requirements on the generic function. Only output is constrained, so I need to hit a few XORs here to satisfy the type system.
Now again, if you'd rather use another implementation that doesn't try to minimize the constraints when writing the final test (and I agree this particular constraint probably wouldn't change anything), I'm absolutely open to it :)

}

quickcheck! {
fn hms_test_qc(test_vec: Vec<i32>) -> () {
Copy link
Collaborator

@mashedcode mashedcode Feb 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "hms" stand for? hash multi set test? Or does it just test some iterator functionality?

Copy link
Author

@Ten0 Ten0 Feb 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, hms stands for "hash multi set". qc is for quickcheck, a crate that allows to test on randomly generated inputs.

@ssrlive
Copy link

ssrlive commented Mar 3, 2023

I need use the BTreeMultiset, I hope @jmitchell can merge this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Iterator could be specialized Need the same with BTreeSet

3 participants