Skip to content

Instantly share code, notes, and snippets.

@dennisvennink
Created June 19, 2018 17:31
Show Gist options
  • Save dennisvennink/7699612547a4d6aae8e2d1b136fceaf2 to your computer and use it in GitHub Desktop.
Save dennisvennink/7699612547a4d6aae8e2d1b136fceaf2 to your computer and use it in GitHub Desktop.
public struct Pair <Type1, Type2> {
public let first: Type1
public let second: Type2
public init (_ first: Type1, _ second: Type2) {
(self.first, self.second) = (first, second)
}
}
extension Pair {
func fill <WrappedType1, WrappedType2> (_ first: WrappedType1, _ second: WrappedType2) -> Pair<WrappedType1, WrappedType2> where Type1 == Optional<WrappedType1>, Type2 == Optional<WrappedType2> {
return Pair<WrappedType1, WrappedType2>(self.first ?? first, self.second ?? second)
}
}
extension Pair where Type1: Sequence, Type2: Sequence {
public enum Zip {
public struct LongestSequence: Sequence {
internal let sequence1: Type1
internal let sequence2: Type2
internal init (_ sequence1: Type1, _ sequence2: Type2) {
(self.sequence1, self.sequence2) = (sequence1, sequence2)
}
public struct Iterator: IteratorProtocol {
internal var iterator1: Type1.Iterator
internal var iterator2: Type2.Iterator
internal var reachedEnd = false
internal init (_ iterator1: Type1.Iterator, _ iterator2: Type2.Iterator) {
(self.iterator1, self.iterator2) = (iterator1, iterator2)
}
public mutating func next() -> (Type1.Iterator.Element?, Type2.Iterator.Element?)? {
if self.reachedEnd {
return nil
}
let element1 = self.iterator1.next()
let element2 = self.iterator2.next()
if element1 == nil && element2 == nil {
self.reachedEnd.toggle()
return nil
}
return (element1, element2)
}
}
public func makeIterator () -> Iterator {
return Iterator(self.sequence1.makeIterator(), self.sequence2.makeIterator())
}
}
public struct ShortestSequence: Sequence {
internal let sequence1: Type1
internal let sequence2: Type2
internal init (_ sequence1: Type1, _ sequence2: Type2) {
(self.sequence1, self.sequence2) = (sequence1, sequence2)
}
public struct Iterator: IteratorProtocol {
internal var iterator1: Type1.Iterator
internal var iterator2: Type2.Iterator
internal var reachedEnd = false
internal init (_ iterator1: Type1.Iterator, _ iterator2: Type2.Iterator) {
(self.iterator1, self.iterator2) = (iterator1, iterator2)
}
public mutating func next() -> (Type1.Iterator.Element, Type2.Iterator.Element)? {
if self.reachedEnd {
return nil
}
guard let element1 = self.iterator1.next(), let element2 = self.iterator2.next() else {
self.reachedEnd.toggle()
return nil
}
return (element1, element2)
}
}
public func makeIterator () -> Iterator {
return Iterator(self.sequence1.makeIterator(), self.sequence2.makeIterator())
}
}
}
public var zip: (shortest: Zip.ShortestSequence, longest: Zip.LongestSequence) {
return (shortest: Zip.ShortestSequence(self.first, self.second), longest: Zip.LongestSequence(self.first, self.second))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment