If this works, you would just need to make sure you have an explicit end condition to get you out of the loop since this kind of range would go in infinitely.
Rather than deleting the comment, this was corrected per @Lantua's comment below.
"Filling the gap" for range expression was pitched a few times before (you can search for Range Expression in #evolution), though I don't think much has come out of it.
FWIW, <.. isn't a valid operator right now as dot-operator must begin with dot.
Please don't do this. That index + 1 is a valid and in-bound index is a very strong and fragile guarantee that works only on Array and ArraySlice. If you so much as to do .lazy.filter, you'd already have a problem.
Given that the OP doesn't tell us what kind of collections we're concerning, it's probably either that, or manipulating the index directly using collection.index(after:), which is already mentioned in the question.
With all that said, you can implement RangeExpression and add operator similar to ..< yourself if you're not let down by the fact that it won't be <.. or >..
And expanding on it a bit, this is because of the limit of character combinations allowed in an operator for it to be parsed unambiguously.
If you need left-open right-closed intervals, I have an incomplete library Interval on GitHub. However, it has some significant disadvantages compared to RangeExpression types.
Not sure what RangeExpression mean here for defining an custom postfix operator to get partial range I want.
Anyway, I don't care what the operator is (a func is okay), only care for getting my suffix partial range without have access to the Collection. I give it a try:
postfix operator |||
extension Comparable {
postfix static func ||| (minimum: Self) -> PartialRangeFrom<Self> where Self: Strideable, Self.Stride: SignedInteger {
// only can do this
// minimum...
// how to advance minimum to exclude the first position?
(minimum...).dropFirst() // error: Referencing instance method 'dropFirst' on 'PartialRangeFrom' requires that 'Self' conform to 'Strideable'
// ^^^ error: Cannot convert return expression of type 'DropFirstSequence<(PartialRangeFrom<Self>)>' to return type 'PartialRangeFrom<Self>'
}
}
Ok, yea, RangeExpression documentation is a little obscure. Though much of it is a convention and not strict API rules/guarantees.
In any case, if you'd like the postfix operator to feel like other range expressions, you're on the right track that comparable||| needs to return a new type that you implement. However, you also need to conform PartialRangeFrom to RangeExpression. That's where you'll get an opportunity to remove the first item, in RangeExpression.relative(to:).
postfix operator |||
struct PartialRangeFrom<Bound: Comparable>: RangeExpression {
var bound: Bound
func contains(_ element: Bound) -> Bool { bound < element }
func relative<C>(to collection: C) -> Range<Bound> where C : Collection, Self.Bound == C.Index {
(collection.index(after: bound)...).relative(to: collection)
}
}
extension Comparable {
postfix static func |||(bound: Self) -> PartialRangeFrom<Self> {
.init(bound: bound)
}
}
let a = [0, 1, 2]
a[a.startIndex|||] // [1, 2]
In this case though, don't forget to document that bound cannot be endIndex, since we're not handling that right now (you can if you'd like to).
So guessing at how things work, from something like this:
someCollection[someRangeExpression]
The compiler must be generating code that calls the someRangeExpression.relative(to:) passing in the Collection to get a Range. This answers my question of how an index can get a hold of a Collection to do index calculation.
that's very interesting that's calling .relative(to:) again...to convert a PartialRangeFrom to a Range...
Things defined in the current module are prioritised over things defined in other modules. That way people can add things to libraries without worrying about breaking source stability too much. It's similar to how variables in inner scopes can shadow the ones in outer scopes. If you want to use the one from standard library, you can still write Swift.PartialRangeFrom