Skip to content

Instantly share code, notes, and snippets.

@airspeedswift
Created December 17, 2016 23:15
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save airspeedswift/dc858ebe7f9932605b29aecf082fac95 to your computer and use it in GitHub Desktop.
Save airspeedswift/dc858ebe7f9932605b29aecf082fac95 to your computer and use it in GitHub Desktop.
Non-empty collection in Swift
protocol NonemptyCollection: Collection {
var first: Iterator.Element { get }
}
enum NonemptyIndex<Base: Collection>: Comparable {
case head
case tail(Base.Index)
static func ==(lhs: NonemptyIndex, rhs: NonemptyIndex) -> Bool {
switch (lhs,rhs) {
case (.head,.head):
return true
case let (.tail(i),.tail(j)):
return i == j
default:
return false
}
}
static func <(lhs: NonemptyIndex, rhs: NonemptyIndex) -> Bool {
switch (lhs,rhs) {
case (.head,.head):
return true
case let (.tail(i),.tail(j)):
return i < j
default:
return false
}
}
}
struct NonemptyCollectionWrapper<Base: Collection>: NonemptyCollection {
let head: Base.Iterator.Element
let tail: Base
typealias Index = NonemptyIndex<Base>
var startIndex: Index { return .head }
var endIndex: Index { return .tail(tail.endIndex) }
subscript(idx: Index) -> Base.Iterator.Element {
switch idx {
case .head: return head
case let .tail(tailIdx):
return tail[tailIdx]
}
}
func index(after: Index) -> Index {
switch after {
case .head: return .tail(tail.startIndex)
case let .tail(tailIdx):
return .tail(tail.index(after: tailIdx))
}
}
var first: Base.Iterator.Element { return head }
}
extension NonemptyCollectionWrapper where Base: BidirectionalCollection {
var last: Base.Iterator.Element { return tail.last ?? head }
}
let list = NonemptyCollectionWrapper(head: 1, tail: [2,3])
let x: Int = list.first
let y: Int = list.last
func f<C: NonemptyCollection>(_ c: C) where C.Iterator.Element == Int {
let i: Int = c.first
print(i)
}
f(list)
let a = Array(list)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment