//! Functional programming with generic sequences //! //! Please see `tests/generics.rs` for examples of how to best use these in your generic functions. use super::ArrayLength; use core::iter::FromIterator; use crate::sequence::*; /// Defines the relationship between one generic sequence and another, /// for operations such as `map` and `zip`. pub unsafe trait MappedGenericSequence: GenericSequence where Self::Length: ArrayLength, { /// Mapped sequence type type Mapped: GenericSequence; } unsafe impl<'a, T, U, S: MappedGenericSequence> MappedGenericSequence for &'a S where &'a S: GenericSequence, S: GenericSequence>::Length>, >::Length: ArrayLength, { type Mapped = >::Mapped; } unsafe impl<'a, T, U, S: MappedGenericSequence> MappedGenericSequence for &'a mut S where &'a mut S: GenericSequence, S: GenericSequence>::Length>, >::Length: ArrayLength, { type Mapped = >::Mapped; } /// Accessor type for a mapped generic sequence pub type MappedSequence = <>::Mapped as GenericSequence>::Sequence; /// Defines functional programming methods for generic sequences pub unsafe trait FunctionalSequence: GenericSequence { /// Maps a `GenericSequence` to another `GenericSequence`. /// /// If the mapping function panics, any already initialized elements in the new sequence /// will be dropped, AND any unused elements in the source sequence will also be dropped. fn map(self, f: F) -> MappedSequence where Self: MappedGenericSequence, Self::Length: ArrayLength, F: FnMut(Self::Item) -> U, { FromIterator::from_iter(self.into_iter().map(f)) } /// Combines two `GenericSequence` instances and iterates through both of them, /// initializing a new `GenericSequence` with the result of the zipped mapping function. /// /// If the mapping function panics, any already initialized elements in the new sequence /// will be dropped, AND any unused elements in the source sequences will also be dropped. #[inline] fn zip(self, rhs: Rhs, f: F) -> MappedSequence where Self: MappedGenericSequence, Rhs: MappedGenericSequence>, Self::Length: ArrayLength + ArrayLength, Rhs: GenericSequence, F: FnMut(Self::Item, Rhs::Item) -> U, { rhs.inverted_zip2(self, f) } /// Folds (or reduces) a sequence of data into a single value. /// /// If the fold function panics, any unused elements will be dropped. fn fold(self, init: U, f: F) -> U where F: FnMut(U, Self::Item) -> U, { self.into_iter().fold(init, f) } } unsafe impl<'a, T, S: GenericSequence> FunctionalSequence for &'a S where &'a S: GenericSequence, { } unsafe impl<'a, T, S: GenericSequence> FunctionalSequence for &'a mut S where &'a mut S: GenericSequence, { }