Skip to content

Commit

Permalink
add zip implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo committed Mar 4, 2024
1 parent 5302d2c commit cc092a6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ mod from_fn;
mod iter;
mod sizes;
mod traits;
mod zip;

pub use crate::{iter::TryFromIteratorError, traits::*};
pub use typenum;
Expand Down
49 changes: 49 additions & 0 deletions src/zip.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Functional programming with [`Array`]s.
// This is modeled after `generic-array::functional`
// see: <https://docs.rs/generic-array/1.0.0/generic_array/functional/index.html>

use crate::{Array, ArraySize};

impl<T, U> Array<T, U>
where
U: ArraySize,
{
/// Combines two `Array` instances and iterates through both of them, initialization a new
/// `Array` with the result of the zipped mapping function.
///
/// If the mapping function panics, any already initialized elements in the new array will
/// be dropped, AND any unused elements in the source arrays will also be dropped.
#[inline(always)]
pub fn zip<Rhs, F, O>(self, rhs: Array<Rhs, U>, f: F) -> Array<O, U>
where
U: ArraySize,
F: FnMut(T, Rhs) -> O,
{
Zipper {
inner: self.into_iter(),
rhs: rhs.into_iter(),
f,
}
.collect()
}
}

struct Zipper<I, R, F> {
inner: I,
rhs: R,
f: F,
}

impl<I, T, R, RT, O, F> Iterator for Zipper<I, R, F>
where
I: Iterator<Item = T>,
R: Iterator<Item = RT>,
F: FnMut(T, RT) -> O,
{
type Item = O;

#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
Some((self.f)(self.inner.next()?, self.rhs.next()?))
}
}
15 changes: 15 additions & 0 deletions tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,18 @@ fn maybe_uninit() {
let array = unsafe { uninit_array.assume_init() };
assert_eq!(array.as_slice(), EXAMPLE_SLICE);
}

#[test]
fn test_functional_map() {
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
let expected = Array::<u8, U4>::from([2, 3, 4, 5]);
assert_eq!(base.map(|item| item + 1), expected);
}

#[test]
fn test_functional_zip() {
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
let with = Array::<u8, U4>::from([2, 3, 4, 5]);
let expected = Array::<u8, U4>::from([2, 6, 12, 20]);
assert_eq!(base.zip(with, |item, rhs| item * rhs), expected);
}

0 comments on commit cc092a6

Please sign in to comment.