-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[Do not merge] [stdlib] IncompleteRange prototype #3737
Conversation
For use when constructing IncompleteRange and IncompleteClosedRange.
Now that there’s a postfix ... operator, this expression fails with a different error from before.
Probably necessary to make -Ounchecked work right.
Instead of passing them as two separate parameters to RangeExpression’s required method.
The Range<Index> versions are fully redundant with the RangeExpression versions, and there’s no need for an override point in this type.
@swift-ci Please smoke test Linux platform |
The smoke test failed because a |
@brentdax traditionally this means we file a bug against the typechecker and press forward. |
@brentdax Hey, I'm still very enthusiastic about this, including the unary range operators. Looks like protocol CompleteRange {
associatedtype Bound : Comparable
var lowerBound : Bound { get }
var upperBound : Bound { get }
}
extension CountableRange : CompleteRange {}
extension CountableClosedRange : CompleteRange {}
func random<R: CompleteRange>(from r: R) -> Int where R.Bound == Int, R: Collection {
let rnd = arc4random_uniform(numericCast(r.count))
return r.lowerBound + Int(rnd)
} |
@dabrahams I don't think The basic problem is that I suppose you could reconceptualize RangeExpression as being start-plus-count: protocol RangeExpression {
associatedtype Bound: Comparable
func lowerBound<C: Collection>(in c: C) -> Bound where C.Index == Bound
func distanceToUpperBound<C: Collection>(in c: C) -> C.IndexDistance where C.Index == Bound
}
extension Range: RangeExpression {
func lowerBound<C: Collection>(in c: C) -> Bound where C.Index == Bound {
return lowerBound
}
func distanceToUpperBound<C: Collection>(in c: C) -> C.IndexDistance where C.Index == Bound {
return c.distance(from: lowerBound, to: upperBound)
}
}
extension ClosedRange: RangeExpression {
func lowerBound<C: Collection>(in c: C) -> Bound where C.Index == Bound {
return lowerBound
}
func distanceToUpperBound<C: Collection>(in c: C) -> C.IndexDistance where C.Index == Bound {
return c.distance(from: lowerBound, to: upperBound) + 1
}
}
func random<R: RangeExpression, C: Collection>(from r: R, in c: C) -> C.Element where R.Bound == C.Index {
let rnd = arc4random_uniform(numericCast(r.distanceToUpperBound(in: c))
return c.index(r.lowerBound(in: c), offsetBy: C.IndexDistance(rnd))
}
func random<R: RangeExpression>(from r: R) -> R.Bound where R: Collection, R.Bound == R.Index {
return random(from: r, in: r)
} But that strikes me as a dirtier design than the "normalize to Honestly, however, I think func random<C: Collection>(from c: C) -> C.Element {
let offset = C.IndexDistance(arc4random_uniform(numericCast(c.count)))
return c[c.index(c.startIndex, offsetBy: offset)]
} This can be used with a countable If so, the I've been experimenting and thinking about this for the last couple months, and I'm actually thinking // Note: I'm going to assume that the eventual design is that all collections should use
// DefaultIndices, and the current C.Indices is only there because conditional conformances
// are needed to eliminate Default{Bidirectional,RandomAccess}Indices.
//
// If this assumption is incorrect, this design may have to become a little more convoluted,
// particularly as regards the recursion anchoring I mention below.
protocol IndexSlice {
associatedtype Bound: Comparable
func makeIndices<C: Collection>(in c: C) -> DefaultIndices<C> where C.Index == Bound
}
extension Range: IndexSlice {
func makeIndices<C: Collection>(in c: C) -> DefaultIndices<C> where C.Index == Bound {
// Note: We'd need a `DefaultIndices.subscript(_: Range<Index>)` to anchor the recursion.
// Perhaps it would have a different name or be an initializer; doesn't really matter.
return c.indices[lowerBound..<upperBound]
}
}
extension ClosedRange: IndexSlice {
func makeIndices<C: Collection>(in c: C) -> DefaultIndices<C> where C.Index == Bound {
return c.indices[lowerBound..<c.index(after: upperBound)]
}
}
// etc. On the protocol Collection {
...
// Implements slicing; you'll use indexSlice.startIndex and .endIndex to figure out what's what.
subscript(_ indexSlice: DefaultIndices<C>) -> SubSequence { get }
}
extension Collection {
// Presumably, this would temporarily be implemented by GYB instead of generics.
subscript<IS: IndexSlice>(_ range: IS) -> SubSequence where IS.Bound == Index {
return self[range.makeIndices(in: self)]
}
}
// Similar for `MutableCollection`, `RangeReplaceableCollection`, et.al. However, I may be overthinking this, and we'd be better off with just a |
@brentdax I agree with you that With regard to looping over indices in the range, can't you just use the let i = a.index(a.startIndex, offsetBy: 3)
for x in a.indices[i...] {
...
} remember,
Why do you think all collections should use
That was my first thought. |
This has been obsoleted by SE-0172, which adopted a different design for the same feature. |
What's in this pull request?
This is a prototype of new APIs from the not-yet-numbered Rationalizing Sequence end-operation names proposal. It includes:
RangeExpression
protocol and related refactoring of subrange handlingIncompleteRange
andIncompleteClosedRange
typesIncompleteRange
andIncompleteClosedRange
IncompleteRange
andIncompleteClosedRange
It does not include:
prefix(upTo:)
,prefix(through:)
, orsuffix(from:)
RangeExpression
, other than the ways it is exercised by existing, source-compatible testsKnown issues:
Int
indices with aString
) is failing because the diagnostics have changed. I have not updated the test because the new diagnostics are less helpful than the old ones.Before merging this pull request to apple/swift repository:
Triggering Swift CI
The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:
Smoke Testing
A smoke test on macOS does the following:
device standard libraries are not built.
version of these tests are not run.
A smoke test on Linux does the following:
tests are not run.
Validation Testing
Lint Testing
Note: Only members of the Apple organization can trigger swift-ci.