[swift-evolution] [Discussion][Expericment] D-like slicing syntax
Daniel Duan
daniel at duan.org
Sat Feb 27 22:12:20 CST 2016
Dave Abrahams via swift-evolution <swift-evolution at ...> writes:
>
>
> on Sat Feb 20 2016, Daniel Duan <swift-evolution <at> swift.org> wrote:
>
> Why not just make
>
> x[..<$-2]
>
> work? You can create unary overloads for ..<
Hi Dave, I took another stab at it today. The code is in the following link as
well as end of this email:
https://gist.github.com/dduan/fcd33a09fae4640fc83c
This implementation is almost good IMO :)
struct Dollar {}
let $ = Dollar()
struct BInt: IntegerLiteralConvertible {
let bool: Bool
let int: UInt
func relativeTo(total: Int) -> Int {
return bool ? total - Int(int) : Int(int)
}
init(_ b: Bool, _ n: UInt) {
bool = b
int = n
}
init(integerLiteral value: Int) {
bool = false
int = UInt(value)
}
}
func -(h: Dollar, d: UInt) -> BInt { return BInt(true, d) }
typealias IncompleteRange = (BInt?, BInt?)
prefix operator ..< {}
prefix func ..<(end: BInt) -> IncompleteRange {
return (nil, end)
}
postfix operator ..< {}
postfix func ..<(start: BInt) -> IncompleteRange {
return (start, nil)
}
prefix operator ... {}
prefix func ...(end: BInt) -> IncompleteRange {
return (nil, BInt(end.bool, end.int+1))
}
postfix operator ... {}
postfix func ...(start: BInt) -> IncompleteRange {
return (start, nil)
}
func ..<(start: BInt, end: BInt) -> IncompleteRange {
return (start, end)
}
func ...(start: BInt, end: BInt) -> IncompleteRange {
return (start, BInt(end.bool, end.int+1))
}
internal func normalize(range: IncompleteRange, total: Int) -> (Int, Int) {
var actualStart = range.0 == nil ? 0 : range.0!.relativeTo(total)
var actualEnd = range.1 == nil ? total : range.1!.relativeTo(total)
actualStart = actualStart < 0 ? total + actualStart : actualStart
actualEnd = actualEnd < 0 ? total + actualEnd : actualEnd
return (actualStart, actualEnd)
}
extension CollectionType {
subscript(halfRange: IncompleteRange) -> Self.SubSequence {
let (safeStart, safeEnd) = normalize(
halfRange,
total: self.count as! Int
)
let safeStartIndex = startIndex.advancedBy(
safeStart as! Self.Index.Distance)
let safeEndIndex = startIndex.advancedBy(
safeEnd as! Self.Index.Distance)
return self[safeStartIndex..<safeEndIndex]
}
}
let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// all of these expression results in [6, 7, 8, 9]
s[6...]
s[($-4)...]
s[6..<s.count]
s[6..<$-0]
s[$-4...9]
More information about the swift-evolution
mailing list