-
Notifications
You must be signed in to change notification settings - Fork 21
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
TreeSet.map losing its ordering when used as Iterable #11987
Comments
I'd like to point out that For spray json you'd actually need something along the lines of "for all pure functions
In other words I'm not sure whether that's better than the current behaviour: In terms of That said having |
There are two There's no way to tell the I guess the reason it was done that way was to keep compatibility with the previous There are a few reasons that the current behavior might never change:
The workaround for Sets is to mostly ignore that Sets inherit from def toSafeIterable[T](s: Set[T]): Iterable[T] = new Iterable[T] { def iterator: Iterator[T] = s.iterator } |
in the same vein: scala/scala-parallel-collections#101 (but the thing lost is parallelism instead of ordering) |
This problem exists on 2.12 and 2.13; we hit the original spray issue with both Scala versions. The linked parallel collections issue is 2.13 only. |
IIUC the only fix for this would be to add overloads of
Otherwise you can never distinguish between the case where you can keep the ordering and where you can't. If you want to keep getting a |
The problem comes from the fact that When you call However, if you upcast the On Scala 2.12, the situation was different but the result was the same (the source collection type was part of the Unfortunately, I don’t see how we could fix this. I think we should live with this issue but maybe document it better? |
There's also this issue: scala> (TreeSet(5,3,2,12,38,2,6,2): Iterable[Int]).map(_ => 5).toList
res1: List[Int] = List(5) So, there we have an
|
This property is not true for all iterables, only for seqs. |
Shouldn't iteration be size- and order-preserving? At least that's my perhaps naive intuitive expectation 🤷 |
This is not the case on |
Still, I find it surprising if order gets lost for types which are ordered initially, and I'm also surprised that |
Though it would be impossible for both those expectations to hold. You can't have |
Technically, that's probably right because descriptions of the operators are vague enough to allow that behavior: E.g.
It only says that the function is called for every element of the source collection and that a new collection is built but not what the exact relationship between source and target collections are. For
This is just false but shows how unclear the semantics of That makes Once again, look at that implementation of def toSafeIterable[T](s: Iterable[T]): Iterable[T] =
new Iterable[T] { def iterator: Iterator[T] = s.iterator } This looks like a no-op but it isn't and that tells a lot. To add a possible explanation of the status quo: since Scala collections are eager, the problem with the generic methods that need to return another collection type are:
So for now, the safe option is to
|
Ouch, this is a problem, indeed!
I disagree. As a user, you can still use I disagree with your conclusion. I think we should fix this problem by better documenting the behavior of |
Maybe I wasn't accurate enough. Iterable may have some useful properties or features in its implementation. In that way it is useful. What I meant that accepting an Iterable as a library writer is not useful because it gives so little guarantees that I cannot safely interface with it. Mixing some useful with some dangerous operations doesn't help in that regard.
That's another example where the features of the concrete types (that happen to be implemented by Iterable) can be useful, but if you happen to come across an instance of such a type disguised as an |
That tends to be correct, yes. Generally, you'll either want an |
(Seems like this has to be a well-known issue/puzzler but I couldn't find one with superficial searching)
It seems that
TreeSet
is not working as expected when it is used as an Iterable.The underlying assumption is that for all
i: Iterable[T]
where the implementing collection is sorted this property should be valid:Without the constraint "where the implementing collection is sorted", it is not expected to be true because
Iterable
can be implemented for unsorted collections.Above I used the vague phrase "not working as expected" because the behavior is not explicitly specified (
TreeSet
does not specify how it implementsIterable
which is a common problem of inheritance) and in absence of a specification it should do the least surprising thing.Was observed here: spray/spray-json#329
The text was updated successfully, but these errors were encountered: