#![allow(nonstandard_style)]
use crate::{MapAllMut, Pick, RePick, Tupl, fns};
pub trait IteratorOfTuplesWithF<retval>:
Iterator<Item: Tupl> + Sized
{
/// Map the item at: (|(x, y)| (f(x), y))
fn map_at<const N: usize>(
self,
f: impl FnMut(<Self::Item as Pick<N>>::At) -> retval,
) -> core::iter::Map<
Self,
impl FnMut(<Self>::Item) -> <<Self>::Item as RePick<N, retval>>::New,
>
where
Self::Item: RePick<N, retval>,
{
self.map(fns::at::<N, _, _>(f))
}
/// filter map the item at: (|(x, y)| f(x).zip(Some(y))
fn filter_map_at<const N: usize>(
self,
mut f: impl FnMut(<Self::Item as Pick<N>>::At) -> Option<retval>,
) -> core::iter::FilterMap<
Self,
impl FnMut(
<Self as Iterator>::Item,
) -> Option<
<<Self as Iterator>::Item as RePick<N, retval>>::New,
>,
>
where
Self::Item: RePick<N, retval>,
{
self.filter_map(move |x| {
let (l, at, r) = x.depict();
f(at).map(|x| Self::Item::unpick(l, x, r))
})
}
/// map the item to just one, then map that one: (|x| f(x.0))
fn map_on<const N: usize>(
self,
f: impl FnMut(<Self::Item as Pick<N>>::At) -> retval,
) -> core::iter::Map<
impl Iterator<Item = <Self::Item as Pick<N>>::At>,
impl FnMut(<Self::Item as Pick<N>>::At) -> retval,
>
where
Self: Iterator<Item: Pick<N>> + Sized,
{
self.on().map(f)
}
fn fmap_on<const N: usize>(
self,
f: impl FnMut(<Self::Item as Pick<N>>::At) -> retval,
) -> core::iter::FlatMap<
core::iter::Map<
Self,
impl FnMut(
<Self as Iterator>::Item,
)
-> <<Self as Iterator>::Item as Pick<N>>::At,
>,
retval,
impl FnMut(<<Self as Iterator>::Item as Pick<N>>::At) -> retval,
>
where
Self::Item: Pick<N>,
retval: IntoIterator,
{
self.on().flat_map(f)
}
}
/// may add more later
pub trait IteratorOfTuples: Iterator<Item: Tupl> + Sized {
/// make it just one: (|x| x.0)
fn on<const N: usize>(
self,
) -> core::iter::Map<
Self,
impl FnMut(
<Self as Iterator>::Item,
) -> <<Self as Iterator>::Item as Pick<N>>::At,
>
where
Self::Item: Pick<N>,
{
self.map(|x| x.pick())
}
fn flatten_on<const N: usize>(
self,
) -> core::iter::Flatten<
core::iter::Map<
Self,
impl FnMut(
<Self as Iterator>::Item,
)
-> <<Self as Iterator>::Item as Pick<N>>::At,
>,
>
where
Self::Item: Pick<N, At: IntoIterator>,
{
self.on().flatten()
}
fn map_all<retval: Tupl, functions: Tupl>(
self,
mut fns: functions,
) -> impl Iterator<Item = retval>
where
Self::Item: MapAllMut<retval, functions>,
{
self.map(move |x| x.map_all_mut(&mut fns))
}
/// filter by item at
///
/// usage:
/// ```rust
/// use ttools::*;
/// // note the `hrf` call.
/// // its necessary because rust is a sad language.
/// let x = std::iter::once((1, 2)).filter_on::<0>(hrf(|&x| x == 1)).next();
/// assert_eq!(x, Some((1, 2)));
/// ````
fn filter_on<const N: usize>(
self,
mut f: impl FnMut(
<<Self::Item as Tupl>::AsRef<'_> as Pick<N>>::At,
) -> bool,
) -> core::iter::Filter<
Self,
impl FnMut(&<Self as Iterator>::Item) -> bool,
>
where
for<'a> <Self::Item as Tupl>::AsRef<'a>: Pick<N>,
{
self.filter(move |x| {
let x = x.as_ref();
let at = x.pick();
f(at)
})
}
}
impl<I: Iterator<Item: Tupl>> IteratorOfTuples for I {}
impl<U, I: Iterator<Item: Tupl>> IteratorOfTuplesWithF<U> for I {}
macro_rules! ref_traits {
($name1: ident, $name2: ident, $ref:ident, $convert:ident $(, $ref_mut:tt )?) => {
/// may add more later
/// Regular
pub trait $name1<'a, T: Tupl + 'a>:
Iterator<Item = &'a $($ref_mut)? T> + Sized
{
fn $convert(
self,
) -> core::iter::Map<Self, fn(& $($ref_mut)? T) -> <T>::$ref<'_>> {
self.map(T::$convert)
}
/// make it just one: (|x| x.0)
fn on<const N: usize>(
self,
) -> impl Iterator<Item = <T::$ref<'a> as Pick<N>>::At>
where
T::$ref<'a>: Pick<N>,
{
self.$convert().on()
}
fn map_all<retval: Tupl, functions: Tupl>(
self,
mut fns: functions,
) -> impl Iterator<Item = retval>
where
T::$ref<'a>: MapAllMut<retval, functions>,
{
self.map(move |x| x.$convert().map_all_mut(&mut fns))
}
fn for_all<const N: usize>(self, f: impl FnMut(<T::$ref<'a> as Pick<N>>::At))
where
T::$ref<'a>: Pick<N> {
self.on().for_each(f)
}
}
/// With f
pub trait $name2<'a, T: Tupl + 'a, retval>:
Iterator<Item = &'a $($ref_mut)? T> + Sized
{
/// Map the item at: (|(x, y)| (f(x), y))
fn map_at<const N: usize>(
self,
f: impl FnMut(<T::$ref<'a> as Pick<N>>::At) -> retval + 'a,
) -> impl Iterator<Item = <T::$ref<'a> as RePick<N, retval>>::New>
where
T::$ref<'a>: RePick<N, retval>,
{
self.$convert().map_at(f)
}
/// map the item to just one, then map that one: (|x| f(x.0))
fn map_on<const N: usize>(
self,
f: impl FnMut(<T::$ref<'a> as Pick<N>>::At) -> retval,
) -> core::iter::Map<
impl Iterator<Item = <T::$ref<'a> as Pick<N>>::At>,
impl FnMut(<T::$ref<'a> as Pick<N>>::At) -> retval,
>
where
T::$ref<'a>: Pick<N>,
{
self.on().map(f)
}
}
impl<'a, T: Tupl + 'a, I: Iterator<Item = &'a $($ref_mut)? T>>
$name1<'a, T> for I
{
}
impl<'a, U, T: Tupl + 'a, I: Iterator<Item = &'a $($ref_mut)? T>>
$name2<'a, T, U> for I
{
}
};
}
ref_traits!(
IteratorOfReferencesToTuple,
IteratorOfReferencesToTupleWithF,
AsRef,
as_ref
);
ref_traits!(
IteratorOfMutableReferencesToTuple,
IteratorOfMutableReferencesToTupleWithF,
AsMut,
as_mut,
mut
);
/// Required to call [`IteratorOfTuplesWithF::filter_map_at`]
pub fn hrf<T, U, F: for<'a> Fn(&'a T) -> U>(f: F) -> F {
f
}
#[test]
fn x() {
let x = [(1, 2), (3, 4)].iter().map_at::<0>(|x| x + 2);
let y = [(1, "a"), (2, "b")]
.iter()
.map_all((|x| x + 1, |x| x.to_uppercase()))
.next_chunk::<2>()
.unwrap();
}