-
Notifications
You must be signed in to change notification settings - Fork 3.1k
SeqMap.keys guarantees only key iteration order #10766
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
Conversation
I think either Doing something in between can probably avoid some surprises but not really prevent bugs. |
Not sure if lrytz agreed to undeprecate, so I pushed it as a separate commit, unsquashed. Sorry, Jenkins. To be clear, this PR was motivated by Ichoran's endorsement on the ticket, that even if
I can report that I do not feel wiser. |
I see the point that returning a Seq doesn't hurt and can prevent surprises. But if we don't actually guarantee anything then the value is very limited, surprises when using I think either |
This is only for SeqMaps that don't yet override. It could be restricted further to SeqMap1..4, to be more conservative. Then we can sort whether it's useful API etc under SIP-51. Otherwise, I'll have to at-notify Ichoran. |
67027de
to
bff3d35
Compare
it's not clear what the API intends:
|
@som-snytt where does this stand, in your opinion? also interested in @scala/collections opinions |
This standard is too high for me. |
I'm pretty sure I've mentioned this before somewhere, but I'd personally prefer that I would also like |
I don't remember why I reopened, but probably because Seth said
which is nerd-sniping as moral imperative. I'll refresh my memory and the branch. |
I see the trouble began with this spurious override in
The override would make sense on grounds of efficiency, but per the docs, anyone who wants this behavior should write it out. Lukas's comment is that the doc for If keys are ordered,
Addtionally, It is a non-goal of this PR to guarantee that As an example, The only reason to prefer I see the ticket is about checking equality. That is an especially weak expectation. Rex suggests the solution in this PR, just make When I touch the code, perhaps my perspective will change, and I'll note that here. |
bff3d35
to
f580d8d
Compare
The Ichoranism on scala/bug#12808
|
That is just java.io.IOException: No space left on device This PR will be squashable: it reverts the deprecated overriding, adds clarifying doc, and also slips in the Ichoranist "make it work" because why not. That calls for a mima exception for the private object, which I did not drill into during this expedition. |
f580d8d
to
87815f5
Compare
87815f5
to
2b71cd0
Compare
Note to self: I ran |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're keeping all 3 methods around I'd like the docs to say when to use which - I don't know at this point.
Is there a big risk that existing custom maps would violate the new iteration order guarantee?
@@ -130,6 +132,7 @@ object SeqMap extends MapFactory[SeqMap] { | |||
f(key1, value1) | |||
f(key2, value2) | |||
} | |||
override def keys: Iterable[K] = Vector(key1, key2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iiuc these overrides wouldn't be needed to support the new iteration order guarantee?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is only for the unreasonable expectation that a.keys == b.keys
for a couple of SeqMap
.
2b71cd0
to
6511259
Compare
I gave it some thought again, because what else are the winter holidays for, and I wavered a moment about whether to keep the deprecation of There is no justification for The clever pattern is that It occurs to me that |
assertSameElements(keys.iterator, sm.keys.iterator) | ||
assertSameElements(vm.keys, sm.keys) | ||
assertEquals(vm.keys, sm.keys) | ||
assertEquals(lm.keys, sm.keys) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final edit added the unreasonable expectation back in. Previously, keys
changed from Set
to Seq
after four elements. "But that's a change of only one letter!"
Undeprecate overriding Map keys
6511259
to
4170e40
Compare
as far as I can see, it should be sufficient to release-note it to give custom map implementers the heads-up |
@som-snytt mind giving the PR title and description your best user-facing, included-in-release notes effort? |
The reading list is my discursive comment from the winter holiday followed by my archeological investigation from the Thanksgiving break. Edit: I feel the need to add, "But don't tell them I told you that." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I keep pushing back... I know you're not responsible for where we are today and you're investing time in improving things.
I'm just still completely unclear when to use keys
vs keySet
. The deprecatedOverriding
said that the two are interchangeable; if we change that, I should be able to tell from the docs which does what (including keysIterator
).
// scala/scala#10766 | ||
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.immutable.SeqMap#EmptySeqMap.keys"), | ||
|
||
// IMPROVE YOUR KARMA use trailing comma |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aka, trailing karma
* By default, the set uses `keysIterator` for iteration and delegates `contains` to the `Map`. | ||
* | ||
* For `Map` implementations with ordered but not sorted keys, such as a `SeqMap`, | ||
* `keys` may efficiently build a representation that preserves order. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two phrases tell me some implementation details and that maybe the order is preserved (but only maybe). I think this is potentially more confusing than helpful...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think may
governs efficiently
, not preserves order
.
@@ -229,6 +242,11 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] | |||
} | |||
|
|||
/** An [[Iterator]] of the keys contained by this map. | |||
* | |||
* If the collection maintains ordered keys, then `keysIterator` respects that order. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is helpful.
* If the collection maintains ordered keys, then `keysIterator` respects that order. | ||
* | ||
* The default implementation uses the iterator of this `Map`, | ||
* but may be overridden for efficiency. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation detail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turtles all the way down.
@@ -207,6 +211,16 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] | |||
} | |||
|
|||
/** An [[Iterable]] collection of the keys contained by this map. | |||
* | |||
* The default implementation returns `keySet`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, but then my next question as a user is: when does it not return keySet
? When should I use this over keySet
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They must read the user manual for their implementation.
* For `Map` implementations with ordered but not sorted keys, such as a `SeqMap`, | ||
* `keys` may efficiently build a representation that preserves order. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation detail?
* Its iterator respects the iteration order of `keysIterator`, such that | ||
* ``` | ||
* keys.iterator.sameElements(keySet.iterator) | ||
* ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that a property that always holds? "Its iterator" - what is that referring to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The subject is keys
, hence keys.iterator
. This is the property, yes. That is, don't use equals
as in OP.
Ah, I didn't read far enough back in the discussion. I only re-opened because Seth but it's impossible to meet the standard set by My opinion would have been just to revert the deprecation, but I don't have actual opinions like Ichoran and NthPortal. This is way too much discussion driven by one user misusing the API (which may be open to abuse). |
I may also have re-opened just for |
Fixes scala/bug#12991
Ensure that
keys
of aSeqMap
isain expected order.Seq
That satisfies the unwritten expectation that
keys
is orderedand mutually comparable.The implementation of the collection returned by
keys
is not specified. As an implementation detail or convenience, it is aVector
for smallSeqMap
s.