Skip to content

Instantly share code, notes, and snippets.

@kazk
Last active August 29, 2015 14:12
Show Gist options
  • Save kazk/7b047c2eec974fc6f8ea to your computer and use it in GitHub Desktop.
Save kazk/7b047c2eec974fc6f8ea to your computer and use it in GitHub Desktop.
// MARK: - zip (longest)
// Zip sequences continue to the end of the longest sequence.
// Treats as if the shorter sequences have .None elements to fill the gap.
// MARK: ([A], [B]) -> [(A?, B?)]
/// Generalized zip2 longest, zipping with the given function instead of a tupling function.
public func zipLongest<A : SequenceType, B : SequenceType, R>
(sequenceA: A, sequenceB: B, with f: (A.Generator.Element?, B.Generator.Element?)->R)
-> SequenceOf<R>
{
let ft = { f($0) } // Turn `(A, B)->R` into `((A, B))->R`
return SequenceOf {_ -> GeneratorOf<R> in
var aG: A.Generator? = sequenceA.generate()
var bG: B.Generator? = sequenceB.generate()
return GeneratorOf {
let nexts = (aG?.next(), bG?.next())
// `nil` out the exhausted generator to prevent any further call to `.next()`
switch nexts { // 2² = 4
case (.None, .None): return nil // ..
case (.Some(_), .Some(_)): break // 11
case (.Some(_), .None): bG = nil // 1.
case (.None, .Some(_)): aG = nil // .1
}
return ft(nexts)
}
}
}
/// zip 2 sequences, zipping through the end of the longest sequence.
public func zipLongest<A : SequenceType, B : SequenceType>
(sequenceA: A, sequenceB: B)
-> SequenceOf<(A.Generator.Element?, B.Generator.Element?)>
{
return zipLongest(sequenceA, sequenceB) { ($0, $1) }
}
// MARK: ([A], [B], [C]) -> [(A?, B?, C?)]
public func zipLongest<A : SequenceType, B : SequenceType, C : SequenceType, R>
(sequenceA: A, sequenceB: B, sequenceC: C,
with f: (A.Generator.Element?, B.Generator.Element?, C.Generator.Element?)->R)
-> SequenceOf<R>
{
let ft = { f($0) } // Turn `(A, B, C)->R` into `((A, B, C))->R`
return SequenceOf {_ -> GeneratorOf<R> in
var aG: A.Generator? = sequenceA.generate()
var bG: B.Generator? = sequenceB.generate()
var cG: C.Generator? = sequenceC.generate()
return GeneratorOf {
let nexts = (aG?.next(), bG?.next(), cG?.next())
// `nil` out the exhausted generator to prevent any further call to `.next()`
switch nexts { // 2³ = 8
case (.None, .None, .None): return nil // ...
case (.Some(_), .Some(_), .Some(_)): break // 111
case (.Some(_), .None, .None): (bG, cG) = (nil, nil) // 1..
case (.None, .Some(_), .None): (aG, cG) = (nil, nil) // .1.
case (.None, .None, .Some(_)): (aG, bG) = (nil, nil) // ..1
case (.None, .Some(_), .Some(_)): aG = nil // .11
case (.Some(_), .None, .Some(_)): bG = nil // 1.1
case (.Some(_), .Some(_), .None): cG = nil // 11.
}
return ft(nexts)
}
}
}
/// zip 3 sequences, stopping when the longest sequence is exhausted
public func zipLongest<A : SequenceType, B : SequenceType, C : SequenceType>
(sequenceA: A, sequenceB: B, sequenceC: C)
-> SequenceOf<(A.Generator.Element?, B.Generator.Element?, C.Generator.Element?)>
{
return zipLongest(sequenceA, sequenceB, sequenceC) { ($0, $1, $2) }
}
// MARK: ([A], [B], [C], [D]) -> [(A?, B?, C?, D?)]
public func zipLongest<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, R>
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D,
with f: (A.Generator.Element?, B.Generator.Element?, C.Generator.Element?, D.Generator.Element?)->R)
-> SequenceOf<R>
{
let ft = { f($0) } // Turn `(A, B, C, D)->R` into `((A, B, C, D))->R`
return SequenceOf {_ -> GeneratorOf<R> in
var aG: A.Generator? = sequenceA.generate()
var bG: B.Generator? = sequenceB.generate()
var cG: C.Generator? = sequenceC.generate()
var dG: D.Generator? = sequenceD.generate()
return GeneratorOf {
let nexts = (aG?.next(), bG?.next(), cG?.next(), dG?.next())
// `nil` out the exhausted generator to prevent any further call to `.next()`
switch nexts { // 2⁴ = 16
case (.None, .None, .None, .None): return nil // ....
case (.Some(_), .Some(_), .Some(_), .Some(_)): break // 1111
case (.Some(_), .None, .None, .None): (bG, cG, dG) = (nil, nil, nil) // 1...
case (.None, .Some(_), .None, .None): (aG, cG, dG) = (nil, nil, nil) // .1..
case (.None, .None, .Some(_), .None): (aG, bG, dG) = (nil, nil, nil) // ..1.
case (.None, .None, .None, .Some(_)): (aG, bG, cG) = (nil, nil, nil) // ...1
case (.Some(_), .Some(_), .None, .None): (cG, dG) = (nil, nil) // 11..
case (.Some(_), .None, .Some(_), .None): (bG, dG) = (nil, nil) // 1.1.
case (.Some(_), .None, .None, .Some(_)): (bG, cG) = (nil, nil) // 1..1
case (.None, .Some(_), .None, .Some(_)): (aG, cG) = (nil, nil) // .1.1
case (.None, .None, .Some(_), .Some(_)): (aG, bG) = (nil, nil) // ..11
case (.None, .Some(_), .Some(_), .None): (aG, dG) = (nil, nil) // .11.
case (.Some(_), .Some(_), .Some(_), .None): dG = nil // 111.
case (.Some(_), .Some(_), .None, .Some(_)): cG = nil // 11.1
case (.Some(_), .None, .Some(_), .Some(_)): bG = nil // 1.11
case (.None, .Some(_), .Some(_), .Some(_)): aG = nil // .111
}
return ft(nexts)
}
}
}
/// zip 4 sequences, stopping when the longest sequence is exhausted
public func zipLongest<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType>
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D)
-> SequenceOf<(A.Generator.Element?, B.Generator.Element?, C.Generator.Element?, D.Generator.Element?)>
{
return zipLongest(sequenceA, sequenceB, sequenceC, sequenceD) { ($0, $1, $2, $3) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment