Last active
April 25, 2018 14:26
-
-
Save Tony-Y/2d9d8960d8e80a45300cca312cb0ec11 to your computer and use it in GitHub Desktop.
Swift Stride Operators: (a..<b)%%step and (a...b)%%step
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
struct StrideIterator<Element : Strideable> { | |
var element: Element | |
let step: Element.Stride | |
} | |
extension StrideIterator : IteratorProtocol where Element : Strideable { | |
mutating func next() -> Element? { | |
guard step != 0 else { return nil } | |
defer { element = element.advanced(by: step) } | |
return element | |
} | |
} | |
struct StrideFrom<Element : Strideable> { | |
var start: Element | |
var step: Element.Stride | |
} | |
extension StrideFrom : Sequence { | |
typealias Iterator = StrideIterator<Element> | |
func makeIterator() -> Iterator { | |
return StrideIterator(element: start, step: step) | |
} | |
} | |
extension StrideFrom { | |
func stop(before end: Element) -> StrideTo<Element> { | |
return stride(from: start, to: end, by: step) | |
} | |
func stop(on end: Element) -> StrideThrough<Element> { | |
return stride(from: start, through: end, by: step) | |
} | |
} | |
func stride<Element: Strideable>(from start: Element, by step: Element.Stride) -> StrideFrom<Element> { | |
return StrideFrom(start: start, step: step) | |
} | |
precedencegroup StrideFormationPrecedence { | |
lowerThan: RangeFormationPrecedence | |
} | |
infix operator %%: StrideFormationPrecedence | |
// Half-open Range Stride | |
func %% <T: Strideable>(left: Range<T>, right: T.Stride) -> StrideTo<T> { | |
if right > 0{ | |
return stride(from: left.lowerBound, to: left.upperBound, by: right) | |
} else { | |
return stride(from: left.upperBound.advanced(by: -1), to: left.lowerBound.advanced(by: -1), by: right) | |
} | |
} | |
func %% <T: Strideable>(left: CountableRange<T>, right: T.Stride) -> StrideTo<T> { | |
if right > 0{ | |
return stride(from: left.lowerBound, to: left.upperBound, by: right) | |
} else { | |
return stride(from: left.upperBound.advanced(by: -1), to: left.lowerBound.advanced(by: -1), by: right) | |
} | |
} | |
// Closed Range Stride | |
func %% <T: Strideable>(left: ClosedRange<T>, right: T.Stride) -> StrideThrough<T> { | |
if right > 0{ | |
return stride(from: left.lowerBound, through: left.upperBound, by: right) | |
} else { | |
return stride(from: left.upperBound, through: left.lowerBound, by: right) | |
} | |
} | |
func %% <T: Strideable>(left: CountableClosedRange<T>, right: T.Stride) -> StrideThrough<T> { | |
if right > 0{ | |
return stride(from: left.lowerBound, through: left.upperBound, by: right) | |
} else { | |
return stride(from: left.upperBound, through: left.lowerBound, by: right) | |
} | |
} | |
// Partial Range From Stride | |
func %% <T: Strideable>(left: CountablePartialRangeFrom<T>, right: T.Stride) -> StrideFrom<T> { | |
if right > 0{ | |
return stride(from: left.lowerBound, by: right) | |
} else { | |
return stride(from: left.lowerBound, by: 0) | |
} | |
} | |
// Partial Range To Stride | |
func %% <T: Strideable>(left: PartialRangeUpTo<T>, right: T.Stride) -> StrideFrom<T> { | |
if right > 0{ | |
return stride(from: left.upperBound, by: 0) | |
} else { | |
return stride(from: left.upperBound.advanced(by: -1), by: right) | |
} | |
} | |
// Partial Range Through Stride | |
func %% <T: Strideable>(left: PartialRangeThrough<T>, right: T.Stride) -> StrideFrom<T> { | |
if right > 0{ | |
return stride(from: left.upperBound, by: 0) | |
} else { | |
return stride(from: left.upperBound, by: right) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment