[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