Last active
February 28, 2016 04:13
-
-
Save dduan/fcd33a09fae4640fc83c to your computer and use it in GitHub Desktop.
D-like slicing syntax tailored for Swift.
This file contains 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 is almost good, if only Swift allows specifying precedence for pre/postfix operators. | |
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] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment