Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 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 Expand Up @@ -229,6 +230,15 @@ where
self.as_mut().iter_mut()
}

/// Returns an array of the same size as `self`, with function `f` applied to each element in
/// order.
pub fn map<F, O>(self, f: F) -> Array<O, U>
where
F: FnMut(T) -> O,
{
self.into_iter().map(f).collect()
}

/// Concatenates `self` with `other`.
#[inline]
pub fn concat<N>(self, other: Array<T, N>) -> Array<T, Sum<U, N>>
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);
}