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
Removing an element from a red-black tree sometimes modifies the remaining key-value pairs #44
Comments
Hey there, thanks for the pull requests! Interest in the library was relatively lacking, but I've actually got a tonne of fixes and a significant overhaul to the mutation API already implemented. Rather than committing them here though, I've been iterating more quickly via a copy of the code in a private repo in which it's being used, in order to iterate faster. I can take some time to update the repo now that I know there's some genuine interest though, if you like. May I ask how you're planning on using it? |
Thanks for the response! I've been working on a performance improvement to ESLint's This library seems to be very well-written, and it would be great if I could use it in ESLint. In order for that to happen, I would need:
|
The Node 4 compatibility changes you mentioned shouldn't be an issue, though I'm curious about the rationale behind new ESLint development needing to support Node 4, given that even Node.js itself is up to version 6 for LTS. Shouldn't legacy users simply continue to use an older version of the ESLint npm package? I've started moving my changes over to the Collectable repo, though there are some things that I've been putting off; specifically to do with updating Set, SortedSet, SortedMap and List to use the new mutation API, and updating the deep operations API to match all the changes I've made across the board. I could easily just push up RBT for you, but there is a chain of dependencies (collectable/core, frptools/core) that are affected as well, and the tooling I have set up is designed to update everything in tandem, which means manually updating/publishing RBT is somewhat more of a fiddly process to execute without inadavertently forgetting one step or another. |
The rationale is mostly due to timing -- I think Node 4 was still in LTS when we started working on prereleases for ESLint 4. There's a good chance we'll drop support for Node 4 in ESLint 5, but since the stable release of ESLint 4 just came out a month ago, we'll probably be supporting Node 4 for at least a few months until ESLint 5 comes out. (We try not to do major releases too frequently, since it's annoying for users to have to upgrade.)
Thanks! |
I'll keep you posted. Feel free to bug me about it :-) |
Oh, I'm not sure how relevant this is to you, but the new version of RedBlackTree has a heavily upgraded iterator to allow fast-tracking traversal from one location to another, such as "next, where the key is greater than X". There is also a diffing function that you can use for easily performing set operations (intersect/subtract/union), and there are a few other handy functions as well. |
Sounds useful! Would that allow a faster way of deleting all nodes in a given range? Currently, I'm doing the equivalent of let nextNode = RBT.find('gte', rangeStart, myTree);
while (nextNode.key < rangeEnd) {
RBT.remove(nextNode.key, myTree);
nextNode = RBT.find('gte', rangeStart, myTree);
} But it seems like using iterators would be faster because I wouldn't have to do a bunch of repeated |
Yes and no; you should not modify a mutable structure while iterating through it, however the persistent/immutable side of things would fit your use case nicely here. The internals of an immutable structure are shared by reference as much as possible, which means you can freeze the old version, clone it to a mutable copy, then iterate through the old one safely and use it as the basis for applying mutations to the copy. The freezing/copying process is very lightweight and does not incur the overhead that you'd normally have to think about when cloning a normal mutable data structure. I've converted all of the collections now, and only have the deep mutations API left to fix. |
That makes sense. Out of interest, would it also work to avoid the iteration/mutation issue by storing a list of keys beforehand? const keysToRemove = [];
for (const entry of /* entries starting with rangeStart */) {
if (entry.key >= rangeEnd) {
break;
}
keysToRemove.push(entry.key);
}
keysToRemove.forEach(key => RBT.remove(key, myTree)); |
That would work, but it'd be less efficient because you'd be performing two iterations instead of one; first to iterate and find the keys to remove, and second to iterate and perform the removals. |
Ok it's all in, with new packages published. Readme files and so forth have not been updated at this stage. Let me know if you have any questions, and feel free to revise your pull requests after updating your code. |
Thanks! Hmm, when I install
I have the following installed:
|
Yeah the dependencies seem to be out of sync. I'm fixing now. |
The packages are supposedly fixed, published and usable via npm... do you have any experience with Travis? For the life of me I can't figure out why it's trying to build with outdated dependencies, and all my attempts to reproduce the issue locally have failed. |
I'm not sure -- for what it's worth, I was able to build from a clean install using the same node and yarn version. Is it possible Travis is caching things somehow? |
When I tried installing on a machine where I'd previously built the old version, I ended up getting similar errors. I was able to fix these by running I'm not sure why the |
Travis still failing. Going to try this suggestion and see if I can figure it out. |
Hey, I noticed you went with |
Hi, sorry about disappearing. There were a few reasons I ended up going with
As before, |
Ah ok, no worries, thanks for the feedback :-) fwiw, my implementation of RBT is a first run at it. There may be numerous opportunities for performance optimisation that remain unexplored, should you ever be looking for a faster version. Fair points otherwise. |
Travis finally building. Node.js 4 removed from the build due to an external build dependency issue, though I think the reason for wanting to support Node.js 4 has gone away now anyway... |
Using
@collectable/red-black-tree@3.7.0
with Node 8.1.3:Expected output:
Actual output:
The text was updated successfully, but these errors were encountered: