-
Notifications
You must be signed in to change notification settings - Fork 58
We need a PositionRange type for ranges of collection positions. #1143
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
Draft
dabrahams
wants to merge
10
commits into
main
Choose a base branch
from
range-of-non-comparable
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
595b197
Remove Comparable requirement from Range bound
dabrahams d2038b3
Use unsafe operations.
dabrahams 58b62b6
Merge branch 'main' into range-of-non-comparable
dabrahams 45c4bf6
Remove haxx
dabrahams 915ef9f
Correct spello
dabrahams 489ef5e
Flesh out tests.
dabrahams b859382
Merge remote-tracking branch 'origin/main' into range-of-non-comparable
dabrahams 1b69469
Really try to fix the windows build.
dabrahams f1e2684
Merge branch 'main' into range-of-non-comparable
dabrahams ba807a5
Apply changes from code review
dabrahams File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 like this change but it prompted me with a question for which I don't have a formed opinion. Does it make sense to have a range of incomparable bounds?
The lower bound must be at least notionally less than the upper bound otherwise the abstraction is just an arbitrary pair. The reason why this requirement isn't enforced by a conformance requirement is that I'd like to avoid requiring
Collection.Position
to beComparable
and yet be able to writec[p0 ..< p1]
for any collectionc
and positionsp0
,p1
therein (similar to C++ ranges). Of course, aCollection.Position
must be at least notionally comparable to justifyp0 ..< p1
making sense. Only the implementation of<
may require access to the collection.The sad part is that most algorithms require
Bound
to be comparable, as the rest of this incomplete implementation already demonstrates. So maybe a range ought to have comparable bounds andp0 ..< p1
whentype(of: c).Position
isn'tComparable
ought to have a different type.Outside the scope of a first release, another idea could be that traits could accept an implicit context so that we could say something along these lines:
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.
Sure, but possibly only contextually less. Consider
ReverseCollection
, which could in principle use the same index type as its Base (this does make me realize that the precondition is wrong—it can't even be upheld in a generic context: given two instances that might or might not be Comparable, you wouldn't know if you could form a Range).is that we'd like to avoid
We have always agreed about that. The cost to tree-structured collections of index comparability is too high.
Really, no. Comparable means “give me any two instances—and no other information—and I can tell you how they are ordered (or equal).” A classic linked list orders its positions, and the order is different from the meanings of those positions when they are treated as bare memory addresses.
All that said, I think there are at least three kinds of range-adjacent things, and using separate types to represent them could make sense:
Strideable
Bound
case).(we also have the partial ranges
x...
,...x
, and..<x
, the first of which could be in any of the categories; the others are both of type 1)We only want to use #1 in collection APIs.
If you want to call #2 a
Range
and find another term for #1, that's fine with me. 1-3 are in some sense a refinement hierarchy (it's possible thatBound
comparability is not implied by being a collection, in which case we have a refinement diamond). I was going to say it's hard to imagine there being more than a single useful representation for #1, but a (position, length) pair is a useful range in its own right, and actually comes up pretty often in algorithms. Being forced to go through a (position, position) interface on these algorithms when what you have is a length means incurring an O(length) cost, and it's even common that the algorithm would not have to traverse all of length otherwise.IMO a comprehensive design that sorts all these things out is an interesting problem, but until we've done that work we should start with this small modification to Swift's design that solves the problem of index comparability.
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.
Separately, with regard to the future suggestion, though I don't know the details of what you have in mind, I can comment on what I'm guessing it means:
Aside from seeming to express something I think we don't want (even the collection shouldn't necessarily be able to act as an O(1) ordering predicate on its indices—and I don't think an O(n) predicate is useful), it looks like it introduces needless complexity. In this world
Comparable
appears to effectively be a multi-type trait, an idea I've found to be unneeded in practice. Essentailly it looks like you're making[value: C.Position, context: C]
conform to aContextuallyComparable
trait, which is something that you can express entirely in terms of a trait bound onC
.But y'know, maybe I just don't understand it yet.
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.
100% agree with everything that you said.