1 | //! Functional programming with generic sequences
|
2 | //!
|
3 | //! Please see `tests/generics.rs` for examples of how to best use these in your generic functions.
|
4 |
|
5 | use super::ArrayLength;
|
6 | use core::iter::FromIterator;
|
7 |
|
8 | use crate::sequence::*;
|
9 |
|
10 | /// Defines the relationship between one generic sequence and another,
|
11 | /// for operations such as `map` and `zip`.
|
12 | pub unsafe trait MappedGenericSequence<T, U>: GenericSequence<T>
|
13 | where
|
14 | Self::Length: ArrayLength<U>,
|
15 | {
|
16 | /// Mapped sequence type
|
17 | type Mapped: GenericSequence<U, Length = Self::Length>;
|
18 | }
|
19 |
|
20 | unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a S
|
21 | where
|
22 | &'a S: GenericSequence<T>,
|
23 | S: GenericSequence<T, Length = <&'a S as GenericSequence<T>>::Length>,
|
24 | <S as GenericSequence<T>>::Length: ArrayLength<U>,
|
25 | {
|
26 | type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
|
27 | }
|
28 |
|
29 | unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a mut S
|
30 | where
|
31 | &'a mut S: GenericSequence<T>,
|
32 | S: GenericSequence<T, Length = <&'a mut S as GenericSequence<T>>::Length>,
|
33 | <S as GenericSequence<T>>::Length: ArrayLength<U>,
|
34 | {
|
35 | type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
|
36 | }
|
37 |
|
38 | /// Accessor type for a mapped generic sequence
|
39 | pub type MappedSequence<S, T, U> =
|
40 | <<S as MappedGenericSequence<T, U>>::Mapped as GenericSequence<U>>::Sequence;
|
41 |
|
42 | /// Defines functional programming methods for generic sequences
|
43 | pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {
|
44 | /// Maps a `GenericSequence` to another `GenericSequence`.
|
45 | ///
|
46 | /// If the mapping function panics, any already initialized elements in the new sequence
|
47 | /// will be dropped, AND any unused elements in the source sequence will also be dropped.
|
48 | fn map<U, F>(self, f: F) -> MappedSequence<Self, T, U>
|
49 | where
|
50 | Self: MappedGenericSequence<T, U>,
|
51 | Self::Length: ArrayLength<U>,
|
52 | F: FnMut(Self::Item) -> U,
|
53 | {
|
54 | FromIterator::from_iter(self.into_iter().map(f))
|
55 | }
|
56 |
|
57 | /// Combines two `GenericSequence` instances and iterates through both of them,
|
58 | /// initializing a new `GenericSequence` with the result of the zipped mapping function.
|
59 | ///
|
60 | /// If the mapping function panics, any already initialized elements in the new sequence
|
61 | /// will be dropped, AND any unused elements in the source sequences will also be dropped.
|
62 | #[inline ]
|
63 | fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
|
64 | where
|
65 | Self: MappedGenericSequence<T, U>,
|
66 | Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
|
67 | Self::Length: ArrayLength<B> + ArrayLength<U>,
|
68 | Rhs: GenericSequence<B, Length = Self::Length>,
|
69 | F: FnMut(Self::Item, Rhs::Item) -> U,
|
70 | {
|
71 | rhs.inverted_zip2(self, f)
|
72 | }
|
73 |
|
74 | /// Folds (or reduces) a sequence of data into a single value.
|
75 | ///
|
76 | /// If the fold function panics, any unused elements will be dropped.
|
77 | fn fold<U, F>(self, init: U, f: F) -> U
|
78 | where
|
79 | F: FnMut(U, Self::Item) -> U,
|
80 | {
|
81 | self.into_iter().fold(init, f)
|
82 | }
|
83 | }
|
84 |
|
85 | unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a S
|
86 | where
|
87 | &'a S: GenericSequence<T>,
|
88 | {
|
89 | }
|
90 |
|
91 | unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a mut S
|
92 | where
|
93 | &'a mut S: GenericSequence<T>,
|
94 | {
|
95 | }
|
96 | |