Last active
August 29, 2015 14:15
-
-
Save kazk/44a9afcdac392b44b7fc to your computer and use it in GitHub Desktop.
Defines zipping functions for types conforming to `SequenceType`.
This file contains hidden or 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
// Defines zipping functions for types conforming to `SequenceType`. | |
// - zip (overloaded up to zip7) | |
// - unzip (overloaded up to unzip7) | |
// - zipLongest (overloaded up to zipLongest4) | |
// | |
// References: | |
// - [Convolution (computer science)]: http://en.wikipedia.org/wiki/Convolution_(computer_science) | |
// MARK: - zip (shortest) | |
// MARK: zip2. ([A], [B]) -> [(A, B)] | |
/// Generalized zip2, zipping with the given function instead of a tupling function. | |
/// | |
/// :param: fn A function which combines 2 elements. | |
/// :returns: A sequence of values fn(a, b) | |
public func zip<A : SequenceType, B : SequenceType, R> | |
(sequenceA: A, sequenceB: B, with fn: (A.Generator.Element, B.Generator.Element)->R) | |
-> SequenceOf<R> | |
{ | |
return SequenceOf {_ -> GeneratorOf<R> in | |
var aG = sequenceA.generate(), bG = sequenceB.generate() | |
return GeneratorOf { | |
switch (aG.next(), bG.next()) { | |
case let (.Some(a), .Some(b)): return fn(a, b) | |
default: return nil | |
} | |
} | |
} | |
} | |
/// zip2 with tupling function. | |
/// | |
/// :returns: A sequence of pairs. | |
public func zip<A : SequenceType, B : SequenceType>(sequenceA: A, sequenceB: B) | |
-> SequenceOf<(A.Generator.Element, B.Generator.Element)> | |
{ | |
return zip(sequenceA, sequenceB) { ($0, $1) } | |
} | |
// MARK: zip3. ([A], [B], [C]) -> [(A, B, C)] | |
/// Generalized zip3, zipping with the given function instead of a tupling function. | |
/// | |
/// :param: fn A function which combines 3 elements. | |
/// :returns: A sequence of values fn(a, b, c). | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, R> | |
(sequenceA: A, sequenceB: B, sequenceC: C, | |
with fn: (A.Generator.Element, B.Generator.Element, C.Generator.Element)->R) | |
-> SequenceOf<R> | |
{ | |
return SequenceOf {_ -> GeneratorOf<R> in | |
var aG = sequenceA.generate(), bG = sequenceB.generate() | |
var cG = sequenceC.generate() | |
return GeneratorOf { | |
switch (aG.next(), bG.next(), cG.next()) { | |
case let (.Some(a), .Some(b), .Some(c)): return fn(a, b, c) | |
default: return nil | |
} | |
} | |
} | |
} | |
/// zip3 with tupling function. | |
/// | |
/// :returns: A sequence of triples. | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType> | |
(sequenceA: A, sequenceB: B, sequenceC: C) | |
-> SequenceOf<(A.Generator.Element, B.Generator.Element, C.Generator.Element)> | |
{ | |
return zip(sequenceA, sequenceB, sequenceC) { ($0, $1, $2) } | |
} | |
// MARK: zip4. ([A], [B], [C], [D]) -> [(A, B, C, D)] | |
/// Generalized zip4, zipping with the given function instead of a tupling function. | |
/// | |
/// :param: fn A function which combines 4 elements. | |
/// :returns: A sequence of values fn(a, b, c, d). | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, R> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, | |
with fn: (A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element)->R) | |
-> SequenceOf<R> | |
{ | |
return SequenceOf {_ -> GeneratorOf<R> in | |
var aG = sequenceA.generate(), bG = sequenceB.generate() | |
var cG = sequenceC.generate(), dG = sequenceD.generate() | |
return GeneratorOf { | |
switch (aG.next(), bG.next(), cG.next(), dG.next()) { | |
case let (.Some(a), .Some(b), .Some(c), .Some(d)): return fn(a, b, c, d) | |
default: return nil | |
} | |
} | |
} | |
} | |
/// zip4 with tupling function. | |
/// | |
/// :returns: Sequence of quadruples. | |
public func zip<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 zip(sequenceA, sequenceB, sequenceC, sequenceD) { ($0, $1, $2, $3) } | |
} | |
// MARK: zip5. ([A], [B], [C], [D], [E]) -> [(A, B, C, D, E)] | |
/// Generalized zip5, zipping with the given function instead of a tupling function. | |
/// | |
/// :param: fn A function which combines 5 elements. | |
/// :returns: A sequence of values fn(a, b, c, d, e). | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, E : SequenceType, R> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, sequenceE: E, | |
with fn: (A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element, E.Generator.Element)->R) | |
-> SequenceOf<R> | |
{ | |
return SequenceOf {_ -> GeneratorOf<R> in | |
var aG = sequenceA.generate(), bG = sequenceB.generate() | |
var cG = sequenceC.generate(), dG = sequenceD.generate() | |
var eG = sequenceE.generate() | |
return GeneratorOf { | |
switch (aG.next(), bG.next(), cG.next(), dG.next(), eG.next()) { | |
case let (.Some(a), .Some(b), .Some(c), .Some(d), .Some(e)): return fn(a, b, c, d, e) | |
default: return nil | |
} | |
} | |
} | |
} | |
/// zip5 with tupling function. | |
/// | |
/// :returns: Sequence of 5-Tuples. | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, E : SequenceType> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, sequenceE: E) | |
-> SequenceOf<(A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element, E.Generator.Element)> | |
{ | |
return zip(sequenceA, sequenceB, sequenceC, sequenceD, sequenceE) { ($0, $1, $2, $3, $4) } | |
} | |
// MARK: zip6. ([A], [B], [C], [D], [E], [F]) -> [(A, B, C, D, E, F)] | |
/// Generalized zip6, zipping with the given function instead of a tupling function. | |
/// | |
/// :param: fn A function which combines 6 elements. | |
/// :returns: A sequence of values fn(a, b, c, d, e, f). | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, E : SequenceType, F : SequenceType, R> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, sequenceE: E, sequenceF: F, | |
with fn: (A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element, E.Generator.Element, F.Generator.Element)->R) | |
-> SequenceOf<R> | |
{ | |
return SequenceOf {_ -> GeneratorOf<R> in | |
var aG = sequenceA.generate(), bG = sequenceB.generate() | |
var cG = sequenceC.generate(), dG = sequenceD.generate() | |
var eG = sequenceE.generate(), fG = sequenceF.generate() | |
return GeneratorOf { | |
switch (aG.next(), bG.next(), cG.next(), dG.next(), eG.next(), fG.next()) { | |
case let (.Some(a), .Some(b), .Some(c), .Some(d), .Some(e), .Some(f)): return fn(a, b, c, d, e, f) | |
default: return nil | |
} | |
} | |
} | |
} | |
/// zip6 with tupling function. | |
/// | |
/// :returns: Sequence of 6-Tuples. | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, E : SequenceType, F : SequenceType> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, sequenceE: E, sequenceF: F) | |
-> SequenceOf<(A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element, E.Generator.Element, F.Generator.Element)> | |
{ | |
return zip(sequenceA, sequenceB, sequenceC, sequenceD, sequenceE, sequenceF) { ($0, $1, $2, $3, $4, $5) } | |
} | |
// MARK: zip7. ([A], [B], [C], [D], [E], [F], [G]) -> [(A, B, C, D, E, F, G)] | |
/// Generalized zip7, zipping with the given function instead of a tupling function. | |
/// | |
/// :param: fn A function which combines 7 elements. | |
/// :returns: A sequence of values fn(a, b, c, d, e, f, g). | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, E : SequenceType, F : SequenceType, G : SequenceType, R> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, sequenceE: E, sequenceF: F, sequenceG: G, | |
with fn: (A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element, E.Generator.Element, F.Generator.Element, G.Generator.Element)->R) | |
-> SequenceOf<R> | |
{ | |
return SequenceOf {_ -> GeneratorOf<R> in | |
var aG = sequenceA.generate(), bG = sequenceB.generate() | |
var cG = sequenceC.generate(), dG = sequenceD.generate() | |
var eG = sequenceE.generate(), fG = sequenceF.generate() | |
var gG = sequenceG.generate() | |
return GeneratorOf { | |
switch (aG.next(), bG.next(), cG.next(), dG.next(), eG.next(), fG.next(), gG.next()) { | |
case let (.Some(a), .Some(b), .Some(c), .Some(d), .Some(e), .Some(f), .Some(g)): return fn(a, b, c, d, e, f, g) | |
default: return nil | |
} | |
} | |
} | |
} | |
/// zip7 with tupling function. | |
/// | |
/// :returns: Sequence of 7-Tuples. | |
public func zip<A : SequenceType, B : SequenceType, C : SequenceType, D : SequenceType, E : SequenceType, F : SequenceType, G : SequenceType> | |
(sequenceA: A, sequenceB: B, sequenceC: C, sequenceD: D, sequenceE: E, sequenceF: F, sequenceG: G) | |
-> SequenceOf<(A.Generator.Element, B.Generator.Element, C.Generator.Element, D.Generator.Element, E.Generator.Element, F.Generator.Element, G.Generator.Element)> | |
{ | |
return zip(sequenceA, sequenceB, sequenceC, sequenceD, sequenceE, sequenceF, sequenceG) { | |
($0, $1, $2, $3, $4, $5, $6) | |
} | |
} | |
// MARK: - unzip | |
//func unzip<S : SequenceType, A, B where S.Generator.Element == (A, B)>(s: S) -> ([A], [B]) { | |
//} | |
// MARK: unzip2. [(A, B)] -> ([A], [B]) | |
/// Transforms an array of N-Tuple into N arrays. | |
/// Elements of each tuple are collected into corresponding array in returned tuple. | |
/// | |
/// :param: array An array of pairs (2-Tuple). | |
/// :returns: A tuple of 2 arrays. | |
public func unzip<A, B>(array: [(A, B)]) -> ([A], [B]) { | |
let N = array.count | |
var aa: [A] = []; aa.reserveCapacity(N) | |
var bb: [B] = []; bb.reserveCapacity(N) | |
for (a, b) in array { | |
aa.append(a) | |
bb.append(b) | |
} | |
return (aa, bb) | |
} | |
/// :param: sequence A sequence of pairs (2-Tuple). | |
/// :returns: A tuple of 2 arrays. | |
public func unzip<A, B>(sequence: SequenceOf<(A, B)>) -> ([A], [B]) { | |
return unzip(Array(sequence)) | |
} | |
// MARK: unzip3. [(A, B, C)] -> ([A], [B], [C]) | |
/// Transforms an array of N-Tuple into N arrays. | |
/// Elements of each tuple are collected into corresponding array in returned tuple. | |
/// | |
/// :param: array An array of triples (3-Tuple). | |
/// :returns: A tuple of 3 arrays. | |
public func unzip<A, B, C>(array: [(A, B, C)]) -> ([A], [B], [C]) { | |
let N = array.count | |
var aa: [A] = []; aa.reserveCapacity(N) | |
var bb: [B] = []; bb.reserveCapacity(N) | |
var cc: [C] = []; cc.reserveCapacity(N) | |
for (a, b, c) in array { | |
aa.append(a) | |
bb.append(b) | |
cc.append(c) | |
} | |
return (aa, bb, cc) | |
} | |
/// :param: sequence A sequence of triples (3-Tuple). | |
/// :returns: A tuple of 3 arrays. | |
public func unzip<A, B, C>(sequence: SequenceOf<(A, B, C)>) -> ([A], [B], [C]) { | |
return unzip(Array(sequence)) | |
} | |
// MARK: unzip4. [(A, B, C, D)] -> ([A], [B], [C], [D]) | |
/// Transforms an array of N-Tuple into N arrays. | |
/// Elements of each tuple are collected into corresponding array in returned tuple. | |
/// | |
/// :param: array An array of quadruples (4-Tuple). | |
/// :returns: A tuple of 4 arrays. | |
public func unzip<A, B, C, D>(array: [(A, B, C, D)]) -> ([A], [B], [C], [D]) { | |
let N = array.count | |
var aa: [A] = []; aa.reserveCapacity(N) | |
var bb: [B] = []; bb.reserveCapacity(N) | |
var cc: [C] = []; cc.reserveCapacity(N) | |
var dd: [D] = []; dd.reserveCapacity(N) | |
for (a, b, c, d) in array { | |
aa.append(a) | |
bb.append(b) | |
cc.append(c) | |
dd.append(d) | |
} | |
return (aa, bb, cc, dd) | |
} | |
/// :param: sequence A sequence of quadruples (4-Tuple). | |
/// :returns: A tuple of 4 arrays. | |
public func unzip<A, B, C, D>(sequence: SequenceOf<(A, B, C, D)>) -> ([A], [B], [C], [D]) { | |
return unzip(Array(sequence)) | |
} | |
// MARK: unzip5. [(A, B, C, D, E)] -> ([A], [B], [C], [D], [E]) | |
/// Transforms an array of N-Tuple into N arrays. | |
/// Elements of each tuple are collected into corresponding array in returned tuple. | |
/// | |
/// :param: array An array of 5-Tuples. | |
/// :returns: A tuple of 5 arrays. | |
public func unzip<A, B, C, D, E>(array: [(A, B, C, D, E)]) | |
-> ([A], [B], [C], [D], [E]) | |
{ | |
let N = array.count | |
var aa: [A] = []; aa.reserveCapacity(N) | |
var bb: [B] = []; bb.reserveCapacity(N) | |
var cc: [C] = []; cc.reserveCapacity(N) | |
var dd: [D] = []; dd.reserveCapacity(N) | |
var ee: [E] = []; ee.reserveCapacity(N) | |
for (a, b, c, d, e) in array { | |
aa.append(a) | |
bb.append(b) | |
cc.append(c) | |
dd.append(d) | |
ee.append(e) | |
} | |
return (aa, bb, cc, dd, ee) | |
} | |
/// :param: sequence A sequence of 5-Tuples. | |
/// :returns: A tuple of 5 arrays. | |
public func unzip<A, B, C, D, E>(sequence: SequenceOf<(A, B, C, D, E)>) | |
-> ([A], [B], [C], [D], [E]) | |
{ | |
return unzip(Array(sequence)) | |
} | |
// MARK: unzip6. [(A, B, C, D, E, F)] -> ([A], [B], [C], [D], [E], [F]) | |
/// Transforms an array of N-Tuple into N arrays. | |
/// Elements of each tuple are collected into corresponding array in returned tuple. | |
/// | |
/// :param: array An array of 6-Tuples. | |
/// :returns: A tuple of 6 arrays. | |
public func unzip<A, B, C, D, E, F>(array: [(A, B, C, D, E, F)]) | |
-> ([A], [B], [C], [D], [E], [F]) | |
{ | |
let N = array.count | |
var aa: [A] = []; aa.reserveCapacity(N) | |
var bb: [B] = []; bb.reserveCapacity(N) | |
var cc: [C] = []; cc.reserveCapacity(N) | |
var dd: [D] = []; dd.reserveCapacity(N) | |
var ee: [E] = []; ee.reserveCapacity(N) | |
var ff: [F] = []; ff.reserveCapacity(N) | |
for (a, b, c, d, e, f) in array { | |
aa.append(a) | |
bb.append(b) | |
cc.append(c) | |
dd.append(d) | |
ee.append(e) | |
ff.append(f) | |
} | |
return (aa, bb, cc, dd, ee, ff) | |
} | |
/// :param: sequence A sequence of 6-Tuples. | |
/// :returns: A tuple of 6 arrays. | |
public func unzip<A, B, C, D, E, F>(sequence: SequenceOf<(A, B, C, D, E, F)>) | |
-> ([A], [B], [C], [D], [E], [F]) | |
{ | |
return unzip(Array(sequence)) | |
} | |
// MARK: unzip7. [(A, B, C, D, E, F, G)] -> ([A], [B], [C], [D], [E], [F], [G]) | |
/// Transforms an array of N-Tuple into N arrays. | |
/// Elements of each tuple are collected into corresponding array in returned tuple. | |
/// | |
/// :param: array An array of 7-Tuples. | |
/// :returns: A tuple of 7 arrays. | |
public func unzip<A, B, C, D, E, F, G>(array: [(A, B, C, D, E, F, G)]) | |
-> ([A], [B], [C], [D], [E], [F], [G]) | |
{ | |
let N = array.count | |
var aa: [A] = []; aa.reserveCapacity(N) | |
var bb: [B] = []; bb.reserveCapacity(N) | |
var cc: [C] = []; cc.reserveCapacity(N) | |
var dd: [D] = []; dd.reserveCapacity(N) | |
var ee: [E] = []; ee.reserveCapacity(N) | |
var ff: [F] = []; ff.reserveCapacity(N) | |
var gg: [G] = []; gg.reserveCapacity(N) | |
for (a, b, c, d, e, f, g) in array { | |
aa.append(a) | |
bb.append(b) | |
cc.append(c) | |
dd.append(d) | |
ee.append(e) | |
ff.append(f) | |
gg.append(g) | |
} | |
return (aa, bb, cc, dd, ee, ff, gg) | |
} | |
/// :param: sequence A sequence of 7-Tuples. | |
/// :returns: A tuple of 7 arrays. | |
public func unzip<A, B, C, D, E, F, G>(sequence: SequenceOf<(A, B, C, D, E, F, G)>) | |
-> ([A], [B], [C], [D], [E], [F], [G]) | |
{ | |
return unzip(Array(sequence)) | |
} | |
// MARK: - zip (longest) | |
// Zip sequences together, stops when all generators are exhausted. | |
// Exausted generators are `nil`ed out, returning `nil` for any further accesss. | |
// MARK: ([A], [B]) -> [(A?, B?)] | |
/// Generalized zip2 longest, zipping with the given function instead of a tupling function. | |
/// | |
/// :returns: A sequence of values f(a?, b?) | |
public func zipLongest<A : SequenceType, B : SequenceType, R> | |
(sequenceA: A, sequenceB: B, with f: (A.Generator.Element?, B.Generator.Element?)->R) | |
-> SequenceOf<R> | |
{ | |
// Wrap function to accept single tuple argument. `(A, B)->R` --> `((A, B))->R` | |
let ft = { f($0) } | |
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) | |
} | |
} | |
} | |
/// zip2 longest with tupling function. | |
/// | |
/// :returns: A sequence of pairs. | |
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?)] | |
/// Generalized zip3 longest, zipping with the given function instead of a tupling function. | |
/// | |
/// :returns: A sequence of values f(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> | |
{ | |
// Wrap function to accept single tuple argument. `(A, B)->R` --> `((A, B))->R` | |
let ft = { f($0) } | |
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) | |
} | |
} | |
} | |
/// zip3 longest with tupling function. | |
/// | |
/// :returns: A sequence of triples. | |
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?)] | |
/// Generalized zip4 longest, zipping with the given function instead of a tupling function. | |
/// | |
/// :returns: A sequence of values f(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> | |
{ | |
// Wrap function to accept single tuple argument. `(A, B)->R` --> `((A, B))->R` | |
let ft = { f($0) } | |
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) // f <| nexts | |
} | |
} | |
} | |
/// zip4 longest with tupling function. | |
/// | |
/// :returns: A sequence of quadruples. | |
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) } | |
} | |
// MARK: - | |
// Example use of `zipLongest` to implement equality of sequences with different element types. | |
/* | |
func equal<A : SequenceType, B : SequenceType> | |
(a: A, b: B, isEquivalent: (A.Generator.Element, B.Generator.Element)->Bool) | |
-> Bool | |
{ | |
for pair in zipLongest(a, b) { | |
switch pair { | |
case (.None, .None): preconditionFailure("(.None, .None)") | |
case (.None, .Some(_)), (.Some(_), .None): return false | |
case let (.Some(x), .Some(y)): | |
if !isEquivalent(x, y) { return false } | |
break | |
} | |
} | |
return true | |
} | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment