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
SortedSet/SortedMap defect: invariance violation at Empty #3796
Comments
Imported From: https://issues.scala-lang.org/browse/SI-3796?orig=1
|
@lrytz said: |
@dcsobral said: The problem is solely with the naive implementation of scala> res49
res54: scala.collection.immutable.RedBlack[Int]#BlackTree[Int] = BlackTree(17,(),BlackTree(14,(),BlackTree(10,(),RedTree(6,(),Empty,Empty),RedTree(12,(),Empty,Empty)),BlackTree(16,(),Empty,Empty)),BlackTree(21,(),BlackTree(19,(),Empty,Empty),RedTree(24,(),BlackTree(22,(),Empty,Empty),BlackTree(29,(),Empty,Empty))))
scala> res49.left
res57: scala.collection.immutable.RedBlack[Int]#Tree[Int] = BlackTree(14,(),BlackTree(10,(),RedTree(6,(),Empty,Empty),RedTree(12,(),Empty,Empty)),BlackTree(16,(),Empty,Empty))
scala> res49.right
res58: scala.collection.immutable.RedBlack[Int]#Tree[Int] = BlackTree(21,(),BlackTree(19,(),Empty,Empty),RedTree(24,(),BlackTree(22,(),Empty,Empty),BlackTree(29,(),Empty,Empty))) Now, when 176 override def range(from: Option[A], until: Option[A]): Tree[B] = {
177 if (from == None && until == None) return this
178 if (from != None && isSmaller(key, from.get)) return right.range(from, until);
179 if (until != None && (isSmaller(until.get,key) || !isSmaller(key,until.get)))
180 return left.range(from, until);
181 val newLeft = left.range(from, None)
182 val newRight = right.range(None, until)
183 if ((newLeft eq left) && (newRight eq right)) this
184 else if (newLeft eq Empty) newRight.upd(key, value);
185 else if (newRight eq Empty) newLeft.upd(key, value);
186 else mkTree(isBlack, key, value, newLeft, newRight)
187 } None of the conditions following it are true either, so scala> res49.left.range(Some(16), None)
res55: scala.collection.immutable.RedBlack[Int]#Tree[Int] = BlackTree(16,(),Empty,Empty)
scala> res49.right.range(None, Some(30))
res56: scala.collection.immutable.RedBlack[Int]#Tree[Int] = BlackTree(21,(),BlackTree(19,(),Empty,Empty),RedTree(24,(),BlackTree(22,(),Empty,Empty),BlackTree(29,(),Empty,Empty))) In fact, such a thing could happen for trees of any depth, which makes me doubtful such a join can be easily and efficiently done. The |
@dcsobral said: |
@lrytz said: |
Makarius (makarius) said: From a user's point of view, I would say plain enumeration of ranges would be fine as a start ... |
Makarius (makarius) said: |
@dcsobral said:
You can get an import scala.collection.immutable.SortedSet
def SortedSetRangeIterator[A](set: SortedSet[A], from: A, until: A)(implicit ord: Ordering[A]) = {
import ord._
set.iterator.dropWhile(_ < from).takeWhile(_ < until)
} Testing this I noticed that I wonder if I should open a new ticket, or leave this to be fixed here, which we'll have to touch |
Makarius (makarius) said:
Err, I wanted to exploit the tree structure, navigating quickly to the starting point and then continuing from there in a linear fashion. The |
Makarius (makarius) said:
Yes, I did stumble across this unexpected behaviour, too. Although I thought it was intentional. Exclusive end range is better of course, and it will save me one special case in chopping off my tree. |
@dcsobral said: |
@dcsobral said: Since I have worked on this patch on a cloned github repo, I have also made a pull request there for the patch, in the change that that's easier. |
@dcsobral said: |
@dcsobral said: The performance shouldn't be particularly bad, though it does create a whole new tree instead of taking advantage of existing elements of the existing tree. Still, this ought to be better than the broken implementation presently available. It is still my intention to pursue a superior fix, but I lost the window to 2.8.1 already, so I'd prefer to have this fix in. |
@axel22 said: Thanks! |
@dcsobral said:
It is buggy. The first "forall" needs to be an "exists", I think. I have always hated figuring forall/exists logic for empty collections... I'm working on fixing the test suit to detect this problem before I work on fixing it (which ought to be trivial, but my record with this ticket has been lousy). |
@dcsobral said: |
@dcsobral said: |
@dcsobral said: |
@dcsobral said: Patch is here: http://github.com/dcsobral/scala/commit/e87ed79e78378b864eacbc498554f224de177ccc However, even though it passed all tests from my test suite (and it didn't pass some when I had something wrong -- which gives me some confidence on the test suite itself :), it is rather big and a bit complex. Commit with care. |
@dcsobral said: |
This is Scala 2.8.0.final or equally a more recent snapshot like scala-2.8.0.r22830-b20100824020153.
The following example makes the Redblack implementation behind SortedSet/SortedMap crash:
Here is the JVM dump:
Maybe some mistake from some literature has been copied here. Something like this has happened to other libraries before.
It might help to look at the following proven implementation
http://isabelle.in.tum.de/dist/library/HOL/Library/RBT_Impl.html
The text was updated successfully, but these errors were encountered: