Skip to content

Instantly share code, notes, and snippets.

@guidomb
Created September 8, 2017 15:03
Show Gist options
  • Save guidomb/883b4fe939c65ff41873cedb330a0738 to your computer and use it in GitHub Desktop.
Save guidomb/883b4fe939c65ff41873cedb330a0738 to your computer and use it in GitHub Desktop.
An example of how I would like custom type conversion to work.
let foo = ZipList(left: [1, 2, 3], center: 4, right: [5, 6, 7])
// This is what I would like to have, a custom type conversion / casting
// ([Element], Element, [Element]) => ZipList<Element>
let bar: ZipList<Int> = ([1, 2, 3], 4, [5, 6, 7])
// ZipList type definition
public struct ZipList<Element>: Collection, CustomDebugStringConvertible {
public var startIndex: Int {
return 0
}
public var endIndex: Int {
return count
}
public var count: Int {
return left.count + right.count + 1
}
public var centerIndex: Int {
return left.count
}
public var debugDescription: String {
return "ZipList(\n\tleft: \(left)\n\tcenter: \(center)\n\tright: \(right))"
}
public let left: [Element]
public let center: Element
public let right: [Element]
public init(element: Element) {
self.init(left: [], center: element, right: [])
}
public init(left: [Element], center: Element, right: [Element]) {
self.left = left
self.center = center
self.right = right
}
public subscript(index: Int) -> Element {
precondition(index >= 0 && index < count, "Index of out bounds")
if index < left.count {
return left[index]
} else if index == left.count {
return center
} else {
return right[index - left.count - 1]
}
}
public func index(after index: Int) -> Int {
return index + 1
}
public func shiftLeft(count: UInt) -> ZipList<Element>? {
guard count <= UInt(right.count) else { return .none }
if count == 0 { return self }
let newLeft = left + [center] + Array(right.dropLast(right.count + 1 - Int(count)))
let newRight = Array(right.dropFirst(Int(count)))
return ZipList(left: newLeft, center: right[Int(count) - 1], right: newRight)
}
public func shiftRight(count: UInt) -> ZipList<Element>? {
guard count <= UInt(left.count) else { return .none }
if count == 0 { return self }
let newLeft = Array(left.dropLast(Int(count)))
let newRight = Array(left.dropFirst(left.count + 1 - Int(count))) + [center] + right
return ZipList(left: newLeft, center: left[left.count - Int(count)], right: newRight)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment