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
RedBlackTreeStrategy throws if value is already in set? #4
Comments
This is by design. There's a problem with making that error optional: there are lots of ways to handle this case and they all make sense. When you try to add a element
I hate the first four options because they encourage buggy code: the differences are so subtle that developers will assume they know what's happening when they actually don't. C++ STL chooses 2; Java, C# and Scala choose 5; JavaScript objects (if you're treating them as hashes/sets of Strings) choose 2; Ruby has undefined behavior, but the implementation seems to be 2; ditto Python. Option 2 is compelling, but it hinders some use cases. I originally used js-sorted-set to maintain a huge list of unique points; the exception helped me pinpoint where I was making mistakes. (In other words: after 10 Option 5 is compelling, but that makes for an unintuitive API. So I chose Option 6. Crashing during development is far better than embedding subtle edge cases in production. Perhaps we should add new convenience methods: I welcome a pull request. |
@mxdubois would you welcome a PR that would address this issue by introducing the concept of "Insert Strategies"? The idea would be to export an enum of possible strategies and have the code react to whichever strategy has been set at instantiation time. Something like what follows: SortedSet.ThrowInsertStrategy = 0;
SortedSet.IgnoreInsertStrategy = 1;
SortedSet.ReplaceInsertStrategy = 2; Then the while (true) {
cmp = compare(value, parent.value);
if (cmp === 0) {
switch(this._insertStrategy) {
case ThrowInsertStrategy:
throw 'Value already in set';
case IgnoreInsertStrategy:
return parent;
case ReplaceInsertStrategy:
parent.value = value;
return parent;
default:
throw 'Unsupported insert strategy';
}
}
leftOrRight = cmp < 0 ? 'left' : 'right';
if (parent[leftOrRight] === null) {
break;
}
parent = parent[leftOrRight];
} |
Apologies Michael, I had meant to tag @adamhooper. |
@jacoscaz sure!
The default should be to throw (so the programmer can learn what the options are). |
Fixed by #7 ! |
Yep -- once we release we can close this :). |
For future readers, the new feature lets you write:
|
Here's the offending line of code: https://github.com/adamhooper/js-sorted-set/blob/master/src/SortedSet/RedBlackTreeStrategy.coffee#L68
I would expect the set to no-op when the value is already in the set. Is there a reason it throws? Or perhaps that just came over from the original source?
The text was updated successfully, but these errors were encountered: