Last active
August 29, 2015 14:12
-
-
Save kazk/7b047c2eec974fc6f8ea to your computer and use it in GitHub Desktop.
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
// 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