Skip to content

Commit b4f248c

Browse files
committed
Add fold method to FunctionalSequence
1 parent 4985a7c commit b4f248c

File tree

4 files changed

+72
-19
lines changed

4 files changed

+72
-19
lines changed

src/functional.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {
4343
/// If the mapping function panics, any already initialized elements in the new sequence
4444
/// will be dropped, AND any unused elements in the source sequence will also be dropped.
4545
fn map<U, F>(self, f: F) -> MappedSequence<Self, T, U>
46-
where
47-
Self: MappedGenericSequence<T, U>,
48-
Self::Length: ArrayLength<U>,
49-
F: FnMut(SequenceItem<Self>) -> U,
46+
where
47+
Self: MappedGenericSequence<T, U>,
48+
Self::Length: ArrayLength<U>,
49+
F: FnMut(SequenceItem<Self>) -> U,
5050
{
5151
FromIterator::from_iter(self.into_iter().map(f))
5252
}
@@ -58,15 +58,25 @@ pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {
5858
/// will be dropped, AND any unused elements in the source sequences will also be dropped.
5959
#[inline]
6060
fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
61-
where
62-
Self: MappedGenericSequence<T, U>,
63-
Rhs: MappedGenericSequence<B, U, Mapped=MappedSequence<Self, T, U>>,
64-
Self::Length: ArrayLength<B> + ArrayLength<U>,
65-
Rhs: GenericSequence<B, Length=Self::Length>,
66-
F: FnMut(SequenceItem<Self>, SequenceItem<Rhs>) -> U,
61+
where
62+
Self: MappedGenericSequence<T, U>,
63+
Rhs: MappedGenericSequence<B, U, Mapped=MappedSequence<Self, T, U>>,
64+
Self::Length: ArrayLength<B> + ArrayLength<U>,
65+
Rhs: GenericSequence<B, Length=Self::Length>,
66+
F: FnMut(SequenceItem<Self>, SequenceItem<Rhs>) -> U,
6767
{
6868
rhs.inverted_zip2(self, f)
6969
}
70+
71+
/// Folds (or reduces) a sequence of data into a single value.
72+
///
73+
/// If the fold function panics, any unused elements will be dropped.
74+
fn fold<U, F>(self, init: U, f: F) -> U
75+
where
76+
F: FnMut(U, SequenceItem<Self>) -> U,
77+
{
78+
self.into_iter().fold(init, f)
79+
}
7080
}
7181

7282
unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a S

src/lib.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,23 @@ where
389389
{
390390
rhs.inverted_zip(self, f)
391391
}
392+
393+
fn fold<U, F>(self, init: U, mut f: F) -> U
394+
where
395+
F: FnMut(U, T) -> U
396+
{
397+
let mut source = ArrayConsumer::new(self);
398+
399+
let ArrayConsumer { ref array, ref mut position } = source;
400+
401+
array.iter().fold(init, |acc, src| {
402+
let value = unsafe { ptr::read(src) };
403+
404+
*position += 1;
405+
406+
f(acc, value)
407+
})
408+
}
392409
}
393410

394411
impl<T, N> GenericArray<T, N>
@@ -526,10 +543,14 @@ mod test {
526543
use functional::*;
527544

528545
let a = black_box(arr![i32; 1, 3, 5, 7]);
529-
let mut b = black_box(arr![i32; 2, 4, 6, 8]);
546+
let b = black_box(arr![i32; 2, 4, 6, 8]);
547+
548+
let c = (&a).zip(b, |l, r| l + r);
530549

531-
let c = (a).zip(&mut b, |l, r| l + *r);
550+
let d = a.fold(0, |a, x| a + x);
532551

533552
assert_eq!(c, arr![i32; 3, 7, 11, 15]);
553+
554+
assert_eq!(d, 16);
534555
}
535556
}

tests/mod.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#[macro_use]
44
extern crate generic_array;
55
use core::cell::Cell;
6-
use core::ops::Drop;
6+
use core::ops::{Add, Drop};
77
use generic_array::GenericArray;
88
use generic_array::sequence::*;
99
use generic_array::functional::*;
@@ -267,4 +267,27 @@ fn test_concat() {
267267

268268
assert_eq!(d, arr![i32; 1]);
269269
assert_eq!(e, arr![i32; 2, 3, 4]);
270+
}
271+
272+
#[test]
273+
fn test_fold() {
274+
let a = arr![i32; 1, 2, 3, 4];
275+
276+
assert_eq!(10, a.fold(0, |a, x| a + x));
277+
}
278+
279+
fn sum_generic<S>(s: S) -> i32
280+
where
281+
S: FunctionalSequence<i32>,
282+
SequenceItem<S>: Add<i32, Output=i32>, // `+`
283+
i32: Add<SequenceItem<S>, Output=i32>, // reflexive
284+
{
285+
s.fold(0, |a, x| a + x)
286+
}
287+
288+
#[test]
289+
fn test_sum() {
290+
let a = sum_generic(arr![i32; 1, 2, 3, 4]);
291+
292+
assert_eq!(a, 10);
270293
}

tests/std.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![recursion_limit="128"]
22

3-
//#[macro_use]
43
extern crate generic_array;
54

65
use std::fmt::Debug;
@@ -11,11 +10,11 @@ use generic_array::sequence::*;
1110
use generic_array::functional::*;
1211

1312
pub fn test_generic<S>(s: S)
14-
where
15-
S: FunctionalSequence<i32>, // `.map`
16-
SequenceItem<S>: Add<i32, Output=i32>, // `+`
17-
S: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
18-
MappedSequence<S, i32, i32>: Debug // println!
13+
where
14+
S: FunctionalSequence<i32>, // `.map`
15+
SequenceItem<S>: Add<i32, Output=i32>, // `+`
16+
S: MappedGenericSequence<i32, i32>, // `i32` -> `i32`
17+
MappedSequence<S, i32, i32>: Debug // println!
1918
{
2019
let a = s.map(|x| x + 1);
2120

0 commit comments

Comments
 (0)