Skip to content

Commit d077d6c

Browse files
committed
1 parent f3cbc52 commit d077d6c

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

src/functional.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//! Functional programming with [`Array`]s.
2+
// This is modeled after `generic-array::functional`
3+
// see: <https://docs.rs/generic-array/1.0.0/generic_array/functional/index.html>
4+
5+
use crate::{Array, ArraySize};
6+
7+
impl<T, U> Array<T, U>
8+
where
9+
U: ArraySize,
10+
{
11+
/// Maps an `Array` to another `Array`
12+
///
13+
/// If the mapping function panics, any already initialized elements in the new array will
14+
/// be dropped, AND any unused elements in the source array will also be dropped.
15+
#[inline(always)]
16+
pub fn map<O, F>(self, f: F) -> Array<O, U>
17+
where
18+
F: FnMut(T) -> O,
19+
{
20+
self.into_iter().map(f).collect()
21+
}
22+
23+
/// Combines two `Array` instances and iterates through both of them, initialization a new
24+
/// `Array` with the result of the zipped mapping function.
25+
///
26+
/// If the mapping function panics, any already initialized elements in the new array will
27+
/// be dropped, AND any unused elements in the source arrays will also be dropped.
28+
#[inline(always)]
29+
pub fn zip<Rhs, F, O>(self, rhs: Array<Rhs, U>, f: F) -> Array<O, U>
30+
where
31+
U: ArraySize,
32+
F: FnMut(T, Rhs) -> O,
33+
{
34+
Zipper {
35+
inner: self.into_iter(),
36+
rhs: rhs.into_iter(),
37+
f,
38+
}
39+
.collect()
40+
}
41+
}
42+
43+
struct Zipper<I, R, F> {
44+
inner: I,
45+
rhs: R,
46+
f: F,
47+
}
48+
49+
impl<I, T, R, RT, O, F> Iterator for Zipper<I, R, F>
50+
where
51+
I: Iterator<Item = T>,
52+
R: Iterator<Item = RT>,
53+
F: FnMut(T, RT) -> O,
54+
{
55+
type Item = O;
56+
57+
#[inline(always)]
58+
fn next(&mut self) -> Option<Self::Item> {
59+
Some((self.f)(self.inner.next()?, self.rhs.next()?))
60+
}
61+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
extern crate std;
8989

9090
mod from_fn;
91+
mod functional;
9192
mod iter;
9293
mod sizes;
9394
mod traits;

tests/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,18 @@ fn maybe_uninit() {
139139
let array = unsafe { uninit_array.assume_init() };
140140
assert_eq!(array.as_slice(), EXAMPLE_SLICE);
141141
}
142+
143+
#[test]
144+
fn test_functional_map() {
145+
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
146+
let expected = Array::<u8, U4>::from([2, 3, 4, 5]);
147+
assert_eq!(base.map(|item| item + 1), expected);
148+
}
149+
150+
#[test]
151+
fn test_functional_zip() {
152+
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
153+
let with = Array::<u8, U4>::from([2, 3, 4, 5]);
154+
let expected = Array::<u8, U4>::from([2, 6, 12, 20]);
155+
assert_eq!(base.zip(with, |item, rhs| item * rhs), expected);
156+
}

0 commit comments

Comments
 (0)