overture_core/
zip_suites.rs

1// Zip sequence utilities for higher-arity operations
2// Equivalent to Swift's zip functions for sequences
3
4use std::iter::{IntoIterator, Iterator};
5
6/// Creates a zip iterator from 3 sequences.
7/// Equivalent to Swift's zip<A, B, C>(_ a: A, _ b: B, _ c: C) -> Zip3Sequence<A, B, C>
8///
9/// # Examples
10/// ```
11/// use overture_core::zip_suites::zip3;
12///
13/// let a = vec![1, 2, 3];
14/// let b = vec![4, 5, 6];
15/// let c = vec![7, 8, 9];
16///
17/// let zipped: Vec<_> = zip3(a, b, c).collect();
18/// assert_eq!(zipped, vec![(1, 4, 7), (2, 5, 8), (3, 6, 9)]);
19/// ```
20pub fn zip3<A, B, C>(a: A, b: B, c: C) -> Zip3Iterator<A::IntoIter, B::IntoIter, C::IntoIter>
21where
22    A: IntoIterator,
23    B: IntoIterator,
24    C: IntoIterator,
25{
26    Zip3Iterator {
27        a: a.into_iter(),
28        b: b.into_iter(),
29        c: c.into_iter(),
30    }
31}
32
33/// Creates a zip iterator from 3 sequences with a transform function.
34/// Equivalent to Swift's zip<A, B, C, Z>(with transform: (A.Element, B.Element, C.Element) -> Z, _ a: A, _ b: B, _ c: C) -> [Z]
35///
36/// # Examples
37/// ```
38/// use overture_core::zip_suites::zip3_with;
39///
40/// let a = vec![1, 2, 3];
41/// let b = vec![4, 5, 6];
42/// let c = vec![7, 8, 9];
43///
44/// let result = zip3_with(|x, y, z| x + y + z, a, b, c);
45/// assert_eq!(result, vec![12, 15, 18]);
46/// ```
47pub fn zip3_with<A, B, C, Z, F>(transform: F, a: A, b: B, c: C) -> Vec<Z>
48where
49    A: IntoIterator,
50    B: IntoIterator,
51    C: IntoIterator,
52    F: Fn(A::Item, B::Item, C::Item) -> Z,
53{
54    zip3(a, b, c).map(|(a, b, c)| transform(a, b, c)).collect()
55}
56
57/// Creates a zip iterator from 4 sequences.
58pub fn zip4<A, B, C, D>(
59    a: A,
60    b: B,
61    c: C,
62    d: D,
63) -> Zip4Iterator<A::IntoIter, B::IntoIter, C::IntoIter, D::IntoIter>
64where
65    A: IntoIterator,
66    B: IntoIterator,
67    C: IntoIterator,
68    D: IntoIterator,
69{
70    Zip4Iterator {
71        a: a.into_iter(),
72        b: b.into_iter(),
73        c: c.into_iter(),
74        d: d.into_iter(),
75    }
76}
77
78/// Creates a zip iterator from 4 sequences with a transform function.
79pub fn zip4_with<A, B, C, D, Z, F>(transform: F, a: A, b: B, c: C, d: D) -> Vec<Z>
80where
81    A: IntoIterator,
82    B: IntoIterator,
83    C: IntoIterator,
84    D: IntoIterator,
85    F: Fn(A::Item, B::Item, C::Item, D::Item) -> Z,
86{
87    zip4(a, b, c, d)
88        .map(|(a, b, c, d)| transform(a, b, c, d))
89        .collect()
90}
91
92/// Creates a zip iterator from 5 sequences.
93pub fn zip5<A, B, C, D, E>(
94    a: A,
95    b: B,
96    c: C,
97    d: D,
98    e: E,
99) -> Zip5Iterator<A::IntoIter, B::IntoIter, C::IntoIter, D::IntoIter, E::IntoIter>
100where
101    A: IntoIterator,
102    B: IntoIterator,
103    C: IntoIterator,
104    D: IntoIterator,
105    E: IntoIterator,
106{
107    Zip5Iterator {
108        a: a.into_iter(),
109        b: b.into_iter(),
110        c: c.into_iter(),
111        d: d.into_iter(),
112        e: e.into_iter(),
113    }
114}
115
116/// Creates a zip iterator from 5 sequences with a transform function.
117pub fn zip5_with<A, B, C, D, E, Z, F>(transform: F, a: A, b: B, c: C, d: D, e: E) -> Vec<Z>
118where
119    A: IntoIterator,
120    B: IntoIterator,
121    C: IntoIterator,
122    D: IntoIterator,
123    E: IntoIterator,
124    F: Fn(A::Item, B::Item, C::Item, D::Item, E::Item) -> Z,
125{
126    zip5(a, b, c, d, e)
127        .map(|(a, b, c, d, e)| transform(a, b, c, d, e))
128        .collect()
129}
130
131/// Creates a zip iterator from 6 sequences.
132pub fn zip6<A, B, C, D, E, F>(
133    a: A,
134    b: B,
135    c: C,
136    d: D,
137    e: E,
138    f: F,
139) -> Zip6Iterator<A::IntoIter, B::IntoIter, C::IntoIter, D::IntoIter, E::IntoIter, F::IntoIter>
140where
141    A: IntoIterator,
142    B: IntoIterator,
143    C: IntoIterator,
144    D: IntoIterator,
145    E: IntoIterator,
146    F: IntoIterator,
147{
148    Zip6Iterator {
149        a: a.into_iter(),
150        b: b.into_iter(),
151        c: c.into_iter(),
152        d: d.into_iter(),
153        e: e.into_iter(),
154        f: f.into_iter(),
155    }
156}
157
158/// Creates a zip iterator from 6 sequences with a transform function.
159pub fn zip6_with<A, B, C, D, E, F, Z, G>(transform: G, a: A, b: B, c: C, d: D, e: E, f: F) -> Vec<Z>
160where
161    A: IntoIterator,
162    B: IntoIterator,
163    C: IntoIterator,
164    D: IntoIterator,
165    E: IntoIterator,
166    F: IntoIterator,
167    G: Fn(A::Item, B::Item, C::Item, D::Item, E::Item, F::Item) -> Z,
168{
169    zip6(a, b, c, d, e, f)
170        .map(|(a, b, c, d, e, f)| transform(a, b, c, d, e, f))
171        .collect()
172}
173
174/// Creates a zip iterator from 7 sequences.
175pub fn zip7<A, B, C, D, E, F, G>(
176    a: A,
177    b: B,
178    c: C,
179    d: D,
180    e: E,
181    f: F,
182    g: G,
183) -> Zip7Iterator<
184    A::IntoIter,
185    B::IntoIter,
186    C::IntoIter,
187    D::IntoIter,
188    E::IntoIter,
189    F::IntoIter,
190    G::IntoIter,
191>
192where
193    A: IntoIterator,
194    B: IntoIterator,
195    C: IntoIterator,
196    D: IntoIterator,
197    E: IntoIterator,
198    F: IntoIterator,
199    G: IntoIterator,
200{
201    Zip7Iterator {
202        a: a.into_iter(),
203        b: b.into_iter(),
204        c: c.into_iter(),
205        d: d.into_iter(),
206        e: e.into_iter(),
207        f: f.into_iter(),
208        g: g.into_iter(),
209    }
210}
211
212/// Creates a zip iterator from 7 sequences with a transform function.
213pub fn zip7_with<A, B, C, D, E, F, G, Z, H>(
214    transform: H,
215    a: A,
216    b: B,
217    c: C,
218    d: D,
219    e: E,
220    f: F,
221    g: G,
222) -> Vec<Z>
223where
224    A: IntoIterator,
225    B: IntoIterator,
226    C: IntoIterator,
227    D: IntoIterator,
228    E: IntoIterator,
229    F: IntoIterator,
230    G: IntoIterator,
231    H: Fn(A::Item, B::Item, C::Item, D::Item, E::Item, F::Item, G::Item) -> Z,
232{
233    zip7(a, b, c, d, e, f, g)
234        .map(|(a, b, c, d, e, f, g)| transform(a, b, c, d, e, f, g))
235        .collect()
236}
237
238/// Creates a zip iterator from 8 sequences.
239pub fn zip8<A, B, C, D, E, F, G, H>(
240    a: A,
241    b: B,
242    c: C,
243    d: D,
244    e: E,
245    f: F,
246    g: G,
247    h: H,
248) -> Zip8Iterator<
249    A::IntoIter,
250    B::IntoIter,
251    C::IntoIter,
252    D::IntoIter,
253    E::IntoIter,
254    F::IntoIter,
255    G::IntoIter,
256    H::IntoIter,
257>
258where
259    A: IntoIterator,
260    B: IntoIterator,
261    C: IntoIterator,
262    D: IntoIterator,
263    E: IntoIterator,
264    F: IntoIterator,
265    G: IntoIterator,
266    H: IntoIterator,
267{
268    Zip8Iterator {
269        a: a.into_iter(),
270        b: b.into_iter(),
271        c: c.into_iter(),
272        d: d.into_iter(),
273        e: e.into_iter(),
274        f: f.into_iter(),
275        g: g.into_iter(),
276        h: h.into_iter(),
277    }
278}
279
280/// Creates a zip iterator from 8 sequences with a transform function.
281pub fn zip8_with<A, B, C, D, E, F, G, H, Z, I>(
282    transform: I,
283    a: A,
284    b: B,
285    c: C,
286    d: D,
287    e: E,
288    f: F,
289    g: G,
290    h: H,
291) -> Vec<Z>
292where
293    A: IntoIterator,
294    B: IntoIterator,
295    C: IntoIterator,
296    D: IntoIterator,
297    E: IntoIterator,
298    F: IntoIterator,
299    G: IntoIterator,
300    H: IntoIterator,
301    I: Fn(A::Item, B::Item, C::Item, D::Item, E::Item, F::Item, G::Item, H::Item) -> Z,
302{
303    zip8(a, b, c, d, e, f, g, h)
304        .map(|(a, b, c, d, e, f, g, h)| transform(a, b, c, d, e, f, g, h))
305        .collect()
306}
307
308/// Creates a zip iterator from 9 sequences.
309pub fn zip9<A, B, C, D, E, F, G, H, I>(
310    a: A,
311    b: B,
312    c: C,
313    d: D,
314    e: E,
315    f: F,
316    g: G,
317    h: H,
318    i: I,
319) -> Zip9Iterator<
320    A::IntoIter,
321    B::IntoIter,
322    C::IntoIter,
323    D::IntoIter,
324    E::IntoIter,
325    F::IntoIter,
326    G::IntoIter,
327    H::IntoIter,
328    I::IntoIter,
329>
330where
331    A: IntoIterator,
332    B: IntoIterator,
333    C: IntoIterator,
334    D: IntoIterator,
335    E: IntoIterator,
336    F: IntoIterator,
337    G: IntoIterator,
338    H: IntoIterator,
339    I: IntoIterator,
340{
341    Zip9Iterator {
342        a: a.into_iter(),
343        b: b.into_iter(),
344        c: c.into_iter(),
345        d: d.into_iter(),
346        e: e.into_iter(),
347        f: f.into_iter(),
348        g: g.into_iter(),
349        h: h.into_iter(),
350        i: i.into_iter(),
351    }
352}
353
354/// Creates a zip iterator from 9 sequences with a transform function.
355pub fn zip9_with<A, B, C, D, E, F, G, H, I, Z, J>(
356    transform: J,
357    a: A,
358    b: B,
359    c: C,
360    d: D,
361    e: E,
362    f: F,
363    g: G,
364    h: H,
365    i: I,
366) -> Vec<Z>
367where
368    A: IntoIterator,
369    B: IntoIterator,
370    C: IntoIterator,
371    D: IntoIterator,
372    E: IntoIterator,
373    F: IntoIterator,
374    G: IntoIterator,
375    H: IntoIterator,
376    I: IntoIterator,
377    J: Fn(A::Item, B::Item, C::Item, D::Item, E::Item, F::Item, G::Item, H::Item, I::Item) -> Z,
378{
379    zip9(a, b, c, d, e, f, g, h, i)
380        .map(|(a, b, c, d, e, f, g, h, i)| transform(a, b, c, d, e, f, g, h, i))
381        .collect()
382}
383
384/// Creates a zip iterator from 10 sequences.
385pub fn zip10<A, B, C, D, E, F, G, H, I, J>(
386    a: A,
387    b: B,
388    c: C,
389    d: D,
390    e: E,
391    f: F,
392    g: G,
393    h: H,
394    i: I,
395    j: J,
396) -> Zip10Iterator<
397    A::IntoIter,
398    B::IntoIter,
399    C::IntoIter,
400    D::IntoIter,
401    E::IntoIter,
402    F::IntoIter,
403    G::IntoIter,
404    H::IntoIter,
405    I::IntoIter,
406    J::IntoIter,
407>
408where
409    A: IntoIterator,
410    B: IntoIterator,
411    C: IntoIterator,
412    D: IntoIterator,
413    E: IntoIterator,
414    F: IntoIterator,
415    G: IntoIterator,
416    H: IntoIterator,
417    I: IntoIterator,
418    J: IntoIterator,
419{
420    Zip10Iterator {
421        a: a.into_iter(),
422        b: b.into_iter(),
423        c: c.into_iter(),
424        d: d.into_iter(),
425        e: e.into_iter(),
426        f: f.into_iter(),
427        g: g.into_iter(),
428        h: h.into_iter(),
429        i: i.into_iter(),
430        j: j.into_iter(),
431    }
432}
433
434/// Creates a zip iterator from 10 sequences with a transform function.
435pub fn zip10_with<A, B, C, D, E, F, G, H, I, J, Z, K>(
436    transform: K,
437    a: A,
438    b: B,
439    c: C,
440    d: D,
441    e: E,
442    f: F,
443    g: G,
444    h: H,
445    i: I,
446    j: J,
447) -> Vec<Z>
448where
449    A: IntoIterator,
450    B: IntoIterator,
451    C: IntoIterator,
452    D: IntoIterator,
453    E: IntoIterator,
454    F: IntoIterator,
455    G: IntoIterator,
456    H: IntoIterator,
457    I: IntoIterator,
458    J: IntoIterator,
459    K: Fn(
460        A::Item,
461        B::Item,
462        C::Item,
463        D::Item,
464        E::Item,
465        F::Item,
466        G::Item,
467        H::Item,
468        I::Item,
469        J::Item,
470    ) -> Z,
471{
472    zip10(a, b, c, d, e, f, g, h, i, j)
473        .map(|(a, b, c, d, e, f, g, h, i, j)| transform(a, b, c, d, e, f, g, h, i, j))
474        .collect()
475}
476
477// Iterator implementations
478
479/// Iterator for zipping 3 sequences.
480pub struct Zip3Iterator<A, B, C> {
481    a: A,
482    b: B,
483    c: C,
484}
485
486impl<A, B, C> Iterator for Zip3Iterator<A, B, C>
487where
488    A: Iterator,
489    B: Iterator,
490    C: Iterator,
491{
492    type Item = (A::Item, B::Item, C::Item);
493
494    fn next(&mut self) -> Option<Self::Item> {
495        match (self.a.next(), self.b.next(), self.c.next()) {
496            (Some(a), Some(b), Some(c)) => Some((a, b, c)),
497            _ => None,
498        }
499    }
500}
501
502/// Iterator for zipping 4 sequences.
503pub struct Zip4Iterator<A, B, C, D> {
504    a: A,
505    b: B,
506    c: C,
507    d: D,
508}
509
510impl<A, B, C, D> Iterator for Zip4Iterator<A, B, C, D>
511where
512    A: Iterator,
513    B: Iterator,
514    C: Iterator,
515    D: Iterator,
516{
517    type Item = (A::Item, B::Item, C::Item, D::Item);
518
519    fn next(&mut self) -> Option<Self::Item> {
520        match (self.a.next(), self.b.next(), self.c.next(), self.d.next()) {
521            (Some(a), Some(b), Some(c), Some(d)) => Some((a, b, c, d)),
522            _ => None,
523        }
524    }
525}
526
527/// Iterator for zipping 5 sequences.
528pub struct Zip5Iterator<A, B, C, D, E> {
529    a: A,
530    b: B,
531    c: C,
532    d: D,
533    e: E,
534}
535
536impl<A, B, C, D, E> Iterator for Zip5Iterator<A, B, C, D, E>
537where
538    A: Iterator,
539    B: Iterator,
540    C: Iterator,
541    D: Iterator,
542    E: Iterator,
543{
544    type Item = (A::Item, B::Item, C::Item, D::Item, E::Item);
545
546    fn next(&mut self) -> Option<Self::Item> {
547        match (
548            self.a.next(),
549            self.b.next(),
550            self.c.next(),
551            self.d.next(),
552            self.e.next(),
553        ) {
554            (Some(a), Some(b), Some(c), Some(d), Some(e)) => Some((a, b, c, d, e)),
555            _ => None,
556        }
557    }
558}
559
560/// Iterator for zipping 6 sequences.
561pub struct Zip6Iterator<A, B, C, D, E, F> {
562    a: A,
563    b: B,
564    c: C,
565    d: D,
566    e: E,
567    f: F,
568}
569
570impl<A, B, C, D, E, F> Iterator for Zip6Iterator<A, B, C, D, E, F>
571where
572    A: Iterator,
573    B: Iterator,
574    C: Iterator,
575    D: Iterator,
576    E: Iterator,
577    F: Iterator,
578{
579    type Item = (A::Item, B::Item, C::Item, D::Item, E::Item, F::Item);
580
581    fn next(&mut self) -> Option<Self::Item> {
582        match (
583            self.a.next(),
584            self.b.next(),
585            self.c.next(),
586            self.d.next(),
587            self.e.next(),
588            self.f.next(),
589        ) {
590            (Some(a), Some(b), Some(c), Some(d), Some(e), Some(f)) => Some((a, b, c, d, e, f)),
591            _ => None,
592        }
593    }
594}
595
596/// Iterator for zipping 7 sequences.
597pub struct Zip7Iterator<A, B, C, D, E, F, G> {
598    a: A,
599    b: B,
600    c: C,
601    d: D,
602    e: E,
603    f: F,
604    g: G,
605}
606
607impl<A, B, C, D, E, F, G> Iterator for Zip7Iterator<A, B, C, D, E, F, G>
608where
609    A: Iterator,
610    B: Iterator,
611    C: Iterator,
612    D: Iterator,
613    E: Iterator,
614    F: Iterator,
615    G: Iterator,
616{
617    type Item = (
618        A::Item,
619        B::Item,
620        C::Item,
621        D::Item,
622        E::Item,
623        F::Item,
624        G::Item,
625    );
626
627    fn next(&mut self) -> Option<Self::Item> {
628        match (
629            self.a.next(),
630            self.b.next(),
631            self.c.next(),
632            self.d.next(),
633            self.e.next(),
634            self.f.next(),
635            self.g.next(),
636        ) {
637            (Some(a), Some(b), Some(c), Some(d), Some(e), Some(f), Some(g)) => {
638                Some((a, b, c, d, e, f, g))
639            }
640            _ => None,
641        }
642    }
643}
644
645/// Iterator for zipping 8 sequences.
646pub struct Zip8Iterator<A, B, C, D, E, F, G, H> {
647    a: A,
648    b: B,
649    c: C,
650    d: D,
651    e: E,
652    f: F,
653    g: G,
654    h: H,
655}
656
657impl<A, B, C, D, E, F, G, H> Iterator for Zip8Iterator<A, B, C, D, E, F, G, H>
658where
659    A: Iterator,
660    B: Iterator,
661    C: Iterator,
662    D: Iterator,
663    E: Iterator,
664    F: Iterator,
665    G: Iterator,
666    H: Iterator,
667{
668    type Item = (
669        A::Item,
670        B::Item,
671        C::Item,
672        D::Item,
673        E::Item,
674        F::Item,
675        G::Item,
676        H::Item,
677    );
678
679    fn next(&mut self) -> Option<Self::Item> {
680        match (
681            self.a.next(),
682            self.b.next(),
683            self.c.next(),
684            self.d.next(),
685            self.e.next(),
686            self.f.next(),
687            self.g.next(),
688            self.h.next(),
689        ) {
690            (Some(a), Some(b), Some(c), Some(d), Some(e), Some(f), Some(g), Some(h)) => {
691                Some((a, b, c, d, e, f, g, h))
692            }
693            _ => None,
694        }
695    }
696}
697
698/// Iterator for zipping 9 sequences.
699pub struct Zip9Iterator<A, B, C, D, E, F, G, H, I> {
700    a: A,
701    b: B,
702    c: C,
703    d: D,
704    e: E,
705    f: F,
706    g: G,
707    h: H,
708    i: I,
709}
710
711impl<A, B, C, D, E, F, G, H, I> Iterator for Zip9Iterator<A, B, C, D, E, F, G, H, I>
712where
713    A: Iterator,
714    B: Iterator,
715    C: Iterator,
716    D: Iterator,
717    E: Iterator,
718    F: Iterator,
719    G: Iterator,
720    H: Iterator,
721    I: Iterator,
722{
723    type Item = (
724        A::Item,
725        B::Item,
726        C::Item,
727        D::Item,
728        E::Item,
729        F::Item,
730        G::Item,
731        H::Item,
732        I::Item,
733    );
734
735    fn next(&mut self) -> Option<Self::Item> {
736        match (
737            self.a.next(),
738            self.b.next(),
739            self.c.next(),
740            self.d.next(),
741            self.e.next(),
742            self.f.next(),
743            self.g.next(),
744            self.h.next(),
745            self.i.next(),
746        ) {
747            (Some(a), Some(b), Some(c), Some(d), Some(e), Some(f), Some(g), Some(h), Some(i)) => {
748                Some((a, b, c, d, e, f, g, h, i))
749            }
750            _ => None,
751        }
752    }
753}
754
755/// Iterator for zipping 10 sequences.
756pub struct Zip10Iterator<A, B, C, D, E, F, G, H, I, J> {
757    a: A,
758    b: B,
759    c: C,
760    d: D,
761    e: E,
762    f: F,
763    g: G,
764    h: H,
765    i: I,
766    j: J,
767}
768
769impl<A, B, C, D, E, F, G, H, I, J> Iterator for Zip10Iterator<A, B, C, D, E, F, G, H, I, J>
770where
771    A: Iterator,
772    B: Iterator,
773    C: Iterator,
774    D: Iterator,
775    E: Iterator,
776    F: Iterator,
777    G: Iterator,
778    H: Iterator,
779    I: Iterator,
780    J: Iterator,
781{
782    type Item = (
783        A::Item,
784        B::Item,
785        C::Item,
786        D::Item,
787        E::Item,
788        F::Item,
789        G::Item,
790        H::Item,
791        I::Item,
792        J::Item,
793    );
794
795    fn next(&mut self) -> Option<Self::Item> {
796        match (
797            self.a.next(),
798            self.b.next(),
799            self.c.next(),
800            self.d.next(),
801            self.e.next(),
802            self.f.next(),
803            self.g.next(),
804            self.h.next(),
805            self.i.next(),
806            self.j.next(),
807        ) {
808            (
809                Some(a),
810                Some(b),
811                Some(c),
812                Some(d),
813                Some(e),
814                Some(f),
815                Some(g),
816                Some(h),
817                Some(i),
818                Some(j),
819            ) => Some((a, b, c, d, e, f, g, h, i, j)),
820            _ => None,
821        }
822    }
823}
824
825#[cfg(test)]
826mod tests {
827    use super::*;
828
829    #[test]
830    fn test_zip3() {
831        let a = vec![1, 2, 3];
832        let b = vec![4, 5, 6];
833        let c = vec![7, 8, 9];
834
835        let zipped: Vec<_> = zip3(a, b, c).collect();
836        assert_eq!(zipped, vec![(1, 4, 7), (2, 5, 8), (3, 6, 9)]);
837    }
838
839    #[test]
840    fn test_zip3_with() {
841        let a = vec![1, 2, 3];
842        let b = vec![4, 5, 6];
843        let c = vec![7, 8, 9];
844
845        let result = zip3_with(|x, y, z| x + y + z, a, b, c);
846        assert_eq!(result, vec![12, 15, 18]);
847    }
848
849    #[test]
850    fn test_zip4() {
851        let a = vec![1, 2, 3];
852        let b = vec![4, 5, 6];
853        let c = vec![7, 8, 9];
854        let d = vec![10, 11, 12];
855
856        let zipped: Vec<_> = zip4(a, b, c, d).collect();
857        assert_eq!(zipped, vec![(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]);
858    }
859
860    #[test]
861    fn test_zip4_with() {
862        let a = vec![1, 2, 3];
863        let b = vec![4, 5, 6];
864        let c = vec![7, 8, 9];
865        let d = vec![10, 11, 12];
866
867        let result = zip4_with(|w, x, y, z| w + x + y + z, a, b, c, d);
868        assert_eq!(result, vec![22, 26, 30]);
869    }
870
871    #[test]
872    fn test_zip5() {
873        let a = vec![1, 2, 3];
874        let b = vec![4, 5, 6];
875        let c = vec![7, 8, 9];
876        let d = vec![10, 11, 12];
877        let e = vec![13, 14, 15];
878
879        let zipped: Vec<_> = zip5(a, b, c, d, e).collect();
880        assert_eq!(
881            zipped,
882            vec![(1, 4, 7, 10, 13), (2, 5, 8, 11, 14), (3, 6, 9, 12, 15)]
883        );
884    }
885
886    #[test]
887    fn test_zip5_with() {
888        let a = vec![1, 2, 3];
889        let b = vec![4, 5, 6];
890        let c = vec![7, 8, 9];
891        let d = vec![10, 11, 12];
892        let e = vec![13, 14, 15];
893
894        let result = zip5_with(|v, w, x, y, z| v + w + x + y + z, a, b, c, d, e);
895        assert_eq!(result, vec![35, 40, 45]);
896    }
897
898    #[test]
899    fn test_zip_different_lengths() {
900        let a = vec![1, 2, 3, 4];
901        let b = vec![5, 6];
902        let c = vec![7, 8, 9];
903
904        let zipped: Vec<_> = zip3(a, b, c).collect();
905        assert_eq!(zipped, vec![(1, 5, 7), (2, 6, 8)]);
906    }
907
908    #[test]
909    fn test_zip_with_strings() {
910        let names = vec!["Alice", "Bob", "Charlie"];
911        let ages = vec![25, 30, 35];
912        let cities = vec!["New York", "London", "Tokyo"];
913
914        let result = zip3_with(
915            |name, age, city| format!("{} is {} years old and lives in {}", name, age, city),
916            names,
917            ages,
918            cities,
919        );
920        assert_eq!(
921            result,
922            vec![
923                "Alice is 25 years old and lives in New York",
924                "Bob is 30 years old and lives in London",
925                "Charlie is 35 years old and lives in Tokyo"
926            ]
927        );
928    }
929}