Sat, 22 Oct 2022 22:28:04 +0300
Convert iteration utilities to GATs
src/maputil.rs | file | annotate | diff | comparison | revisions |
--- a/src/maputil.rs Sat Oct 22 18:12:49 2022 +0300 +++ b/src/maputil.rs Sat Oct 22 22:28:04 2022 +0300 @@ -101,7 +101,7 @@ macro_rules! make_mapmany_mut{ ($name:ident, $name_indexed:ident, $var0:ident $($var:ident)* ; $etype0:ident $($etype:ident)*, $ctype0:ident $($ctype:ident)*) => { - /// Map over multiple [`FixedLength`] container inserting the result in the first. + /// Map over [`FixedLength`] container(s) with mutable references to the first container. #[inline] pub fn $name< $etype0, @@ -118,8 +118,8 @@ zipit.for_each(|tuple_or_singleton!($var0, $($var),*)| f($var0, $($var),*)); } - /// Map over multiple [`FixedLength`] container inserting the result in the first. - /// This version also passes the index to the mapping function. + /// Map over [`FixedLength`] container(s) and element indices + /// with mutable references to the first container. #[inline] pub fn $name_indexed< $etype0, @@ -161,6 +161,7 @@ // } +/// Iterator returned by [`foldmap`][FoldMappable::foldmap] applied to an iterator. pub struct FoldMap<I : Iterator<Item=A>, A, B, J : Copy, F : Fn(J, A) -> (J, B)> { iter : I, f : F, @@ -179,6 +180,7 @@ } } +/// Iterator returned by [`indexmap`][IndexMappable::indexmap] applied to an iterator. pub struct IndexMap<I : Iterator<Item=A>, A, B, F : Fn(usize, A) -> B> { iter : I, f : F, @@ -197,50 +199,63 @@ } } -pub trait FoldMappable<A, B, J, F : Fn(J, A) -> (J, B)> : Sized { - type Output; - /// Fold and map over an array; typically used to count the element while traversing a map - fn foldmap(self, j : J, f : F) -> Self::Output; +/// Trait for things that can be foldmapped. +/// +/// `A` is the type of elements of `Self`, and `J` the accumulator type for the folding. +pub trait FoldMappable<A, J> : Sized { + type Output<B, F> where F : Fn(J, A) -> (J, B); + /// Fold and map over `self` with `f`. `j` is the initial accumulator for folding. + /// + /// The output type depends on the implementation, but will generally have elements of + /// type `B`. + fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F>; } -pub trait IndexMappable<A, B, F : Fn(usize, A) -> B> : Sized { - type Output; - fn indexmap(self, f : F) -> Self::Output; +/// Trait for things that can be indexmapped. +/// +/// `A` is the type of elements of `Self`. +pub trait IndexMappable<A> : Sized { + type Output<B, F> where F : Fn(usize, A) -> B; + /// Map over element indices and elements of `self`. + /// + /// The output type depends on the implementation, but will generally have elements of + /// type `B`. + fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> Self::Output<B, F>; } -impl<'a, A, B, J : Copy, F : Fn(J, &'a A) -> (J, B)> FoldMappable<&'a A, B, J, F> +impl<'a, A, J : Copy> FoldMappable<&'a A, J> for std::slice::Iter<'a, A> { - type Output = FoldMap<Self, &'a A, B, J, F>; + type Output<B, F> = FoldMap<Self, &'a A, B, J, F> where F : Fn(J, &'a A) -> (J, B); #[inline] - fn foldmap(self, j : J, f : F) -> Self::Output { + fn foldmap<B, F : Fn(J, &'a A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F> { FoldMap { iter : self, j, f } } } -impl<'a, A, B, F : Fn(usize, &'a A) -> B> IndexMappable<&'a A, B, F> +impl<'a, A> IndexMappable<&'a A> for std::slice::Iter<'a, A> { - type Output = IndexMap<Self, &'a A, B, F>; + type Output<B, F> = IndexMap<Self, &'a A, B, F> where F : Fn(usize, &'a A) -> B; #[inline] - fn indexmap(self, f : F) -> Self::Output { + fn indexmap<B, F : Fn(usize, &'a A) -> B>(self, f : F) -> Self::Output<B, F> { IndexMap { iter : self, j : 0, f } } } -impl<A, B, J : Copy, F : Fn(J, A) -> (J, B), const N : usize> FoldMappable<A, B, J, F> +impl<A, J : Copy, const N : usize> FoldMappable<A, J> for std::array::IntoIter<A, N> { - type Output = FoldMap<Self, A, B, J, F>; + type Output<B, F> = FoldMap<Self, A, B, J, F> where F : Fn(J, A) -> (J, B); #[inline] - fn foldmap(self, j : J, f : F) -> Self::Output { + fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> Self::Output<B, F> { FoldMap { iter : self, j, f } } } -impl<'a, A, B, F : Fn(usize, A) -> B, const N : usize> IndexMappable<A, B, F> +impl<'a, A, const N : usize> IndexMappable<A> for std::array::IntoIter<A, N> { - type Output = IndexMap<Self, A, B, F>; + type Output<B, F> = IndexMap<Self, A, B, F> where F : Fn(usize, A) -> B; #[inline] - fn indexmap(self, f : F) -> Self::Output { + fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> Self::Output<B, F> { IndexMap { iter : self, j : 0, f } } } @@ -248,10 +263,10 @@ -impl<A, B, J : Copy, F : Fn(J, A) -> (J, B), const N : usize> FoldMappable<A, B, J, F> for [A; N] { - type Output = [B; N]; +impl<A, J : Copy, const N : usize> FoldMappable<A, J> for [A; N] { + type Output<B, F> = [B; N] where F : Fn(J, A) -> (J, B); #[inline] - fn foldmap(self, j : J, f : F) -> [B; N] { + fn foldmap<B, F : Fn(J, A) -> (J, B)>(self, j : J, f : F) -> [B; N] { // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; // let mut res = MaybeUninit::uninit_array::<N>(); // for (a, i) in self.into_iter().zip(0..N) { @@ -266,10 +281,10 @@ } } -impl<A, B, F : Fn(usize, A) -> B, const N : usize> IndexMappable<A, B, F> for [A; N] { - type Output= [B; N]; +impl<A, const N : usize> IndexMappable<A> for [A; N] { + type Output<B, F> = [B; N] where F : Fn(usize, A) -> B; #[inline] - fn indexmap(self, f : F) -> [B; N] { + fn indexmap<B, F : Fn(usize, A) -> B>(self, f : F) -> [B; N] { // //let mut res : [MaybeUninit<B>; N] = unsafe { MaybeUninit::uninit().assume_init() }; // let mut res = MaybeUninit::uninit_array::<N>(); // for (a, i) in self.into_iter().zip(0..N) {