Convert iteration utilities to GATs

Sat, 22 Oct 2022 22:28:04 +0300

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sat, 22 Oct 2022 22:28:04 +0300
changeset 2
ac84e995e119
parent 1
df3901ec2f5d
child 3
20db884b7028

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) {

mercurial