From fa60e844661e2e4120d8241a53d6930067a3b252 Mon Sep 17 00:00:00 2001 From: annieversary Date: Fri, 12 Nov 2021 11:17:11 +0000 Subject: [PATCH] add _head and _tail traversals --- src/traversals/head.rs | 101 +++++++++++++++++++++++++++++++++++++++++ src/traversals/mod.rs | 27 +++++++++++ src/traversals/tail.rs | 98 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 src/traversals/head.rs create mode 100644 src/traversals/tail.rs diff --git a/src/traversals/head.rs b/src/traversals/head.rs new file mode 100644 index 0000000..80a6187 --- /dev/null +++ b/src/traversals/head.rs @@ -0,0 +1,101 @@ +use crate::traversals::{Traversal, TraversalOver, TraversalTraverse}; + +#[derive(Clone, Copy)] +pub struct HeadInner; +#[allow(non_upper_case_globals)] +pub const _head: Traversal = Traversal(HeadInner); + +macro_rules! make_tuples { + (( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => { + impl< $($t,)* > TraversalTraverse<( $($t,)* )> for HeadInner { + type Field = T; + + fn traverse(&self, ( head, $($v,)* ): ($($t,)*)) -> Vec { + vec![head] + } + } + impl< $($t,)* > TraversalOver<( $($t,)* )> for HeadInner { + fn over( + &self, + (head, $($v,)*): ($($t,)*), + mut f: F + ) -> ( $($t,)* ) + where + F: FnMut(Self::Field) -> Self::Field + { + + ( f(head), $($v,)* ) + } + } + + impl<'a, $($t,)* > TraversalTraverse<&'a ( $($t,)* )> for HeadInner { + type Field = &'a T; + + fn traverse(&self, (head, $($v,)* ): &'a ($($t,)*)) -> Vec { + vec![ head ] + } + } + impl<'a, $($t,)* > TraversalTraverse<&'a mut ( $($t,)* )> for HeadInner { + type Field = &'a mut T; + + fn traverse(&self, (head, $($v,)* ): &'a mut ($($t,)*)) -> Vec { + vec![ head ] + } + } + }; +} + +make_tuples!((), (T)); +make_tuples!((_u), (T, U)); +make_tuples!((_u, _v), (T, U, V)); +make_tuples!((_u, _v, _w), (T, U, V, W)); +make_tuples!((_u, _v, _w, _x), (T, U, V, W, X)); +make_tuples!((_u, _v, _w, _x, _y), (T, U, V, W, X, Y)); +make_tuples!((_u, _v, _w, _x, _y, _z), (T, U, V, W, X, Y, Z)); + +macro_rules! make_arrays { + ($n:expr, [$( $v:ident ),*]) => { + impl TraversalTraverse<[T; $n]> for HeadInner { + type Field = T; + + fn traverse(&self, [ head, $($v,)* ]: [T; $n]) -> Vec { + vec![head] + } + } + impl TraversalOver<[T; $n]> for HeadInner { + fn over( + &self, + [ head, $($v,)* ]: [T; $n], + mut fun: F + ) -> [T; $n] + where + F: FnMut(Self::Field) -> Self::Field + { + [fun(head), $(($v),)*] + } + } + + impl<'a, T> TraversalTraverse<&'a [T; $n]> for HeadInner { + type Field = &'a T; + + fn traverse(&self, [head, $($v,)* ]: &'a [T; $n]) -> Vec { + vec![head] + } + } + impl<'a, T> TraversalTraverse<&'a mut [T; $n]> for HeadInner { + type Field = &'a mut T; + + fn traverse(&self, [head, $($v,)* ]: &'a mut [T; $n]) -> Vec { + vec![head] + } + } + }; +} + +make_arrays!(1, []); +make_arrays!(2, [_a]); +make_arrays!(3, [_a, _b]); +make_arrays!(4, [_a, _b, _c]); +make_arrays!(5, [_a, _b, _c, _d]); +make_arrays!(6, [_a, _b, _c, _d, _e]); +make_arrays!(7, [_a, _b, _c, _d, _e, _g]); diff --git a/src/traversals/mod.rs b/src/traversals/mod.rs index 84682e5..c85dcd3 100644 --- a/src/traversals/mod.rs +++ b/src/traversals/mod.rs @@ -4,6 +4,11 @@ pub use both::both; mod each; pub use each::each; +mod head; +pub use head::_head; +mod tail; +pub use tail::_tail; + use crate::{ lenses::{Lens, LensOver, LensView}, prisms::{Prism, PrismPreview}, @@ -154,4 +159,26 @@ mod tests { let res = each(array, |v| v + 1); assert_eq!(res, [2, 3, 4, 5]); } + + #[test] + fn traverse_head_works_on_arrays() { + let array = [1, 2, 3, 4]; + + let res = _head(array); + assert_eq!(res, vec![1,]); + + let res = _head(array, |v| v + 1); + assert_eq!(res, [2, 2, 3, 4,]); + } + + #[test] + fn traverse_tail_works_on_arrays() { + let array = [1, 2, 3, 4]; + + let res = _tail(array); + assert_eq!(res, vec![2, 3, 4]); + + let res = _tail(array, |v| v + 1); + assert_eq!(res, [1, 3, 4, 5]); + } } diff --git a/src/traversals/tail.rs b/src/traversals/tail.rs new file mode 100644 index 0000000..a0f3c95 --- /dev/null +++ b/src/traversals/tail.rs @@ -0,0 +1,98 @@ +use crate::traversals::{Traversal, TraversalOver, TraversalTraverse}; + +#[derive(Clone, Copy)] +pub struct TailInner; +#[allow(non_upper_case_globals)] +pub const _tail: Traversal = Traversal(TailInner); + +macro_rules! make_tuples { + (( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => { + impl TraversalTraverse<( $($t,)* )> for TailInner { + type Field = T; + + fn traverse(&self, ( _, $($v,)* ): ($($t,)*)) -> Vec { + vec![$($v,)*] + } + } + impl TraversalOver<( $($t,)* )> for TailInner { + fn over( + &self, + (head, $($v,)*): ($($t,)*), + mut fun: F + ) -> ( $($t,)* ) + where + F: FnMut(Self::Field) -> Self::Field + { + (head, $( fun($v) ,)*) + } + } + + impl<'a, T> TraversalTraverse<&'a ( $($t,)* )> for TailInner { + type Field = &'a T; + + fn traverse(&self, (_, $($v,)* ): &'a ($($t,)*)) -> Vec { + vec![ $($v,)* ] + } + } + impl<'a, T> TraversalTraverse<&'a mut ( $($t,)* )> for TailInner { + type Field = &'a mut T; + + fn traverse(&self, (_, $($v,)* ): &'a mut ($($t,)*)) -> Vec { + vec![ $($v,)* ] + } + } + }; +} + +make_tuples!((_u), (T, T)); +make_tuples!((_u, _v), (T, T, T)); +make_tuples!((_u, _v, _w), (T, T, T, T)); +make_tuples!((_u, _v, _w, _x), (T, T, T, T, T)); +make_tuples!((_u, _v, _w, _x, _y), (T, T, T, T, T, T)); +make_tuples!((_u, _v, _w, _x, _y, _z), (T, T, T, T, T, T, T)); + +macro_rules! make_arrays { + ($n:expr, [$( $v:ident ),*]) => { + impl TraversalTraverse<[T; $n]> for TailInner { + type Field = T; + + fn traverse(&self, [ _, $($v,)* ]: [T; $n]) -> Vec { + vec![$($v,)*] + } + } + impl TraversalOver<[T; $n]> for TailInner { + fn over( + &self, + [ head, $($v,)* ]: [T; $n], + mut fun: F + ) -> [T; $n] + where + F: FnMut(Self::Field) -> Self::Field + { + [head, $(fun($v),)*] + } + } + + impl<'a, T> TraversalTraverse<&'a [T; $n]> for TailInner { + type Field = &'a T; + + fn traverse(&self, [_, $($v,)* ]: &'a [T; $n]) -> Vec { + vec![$($v,)*] + } + } + impl<'a, T> TraversalTraverse<&'a mut [T; $n]> for TailInner { + type Field = &'a mut T; + + fn traverse(&self, [_, $($v,)* ]: &'a mut [T; $n]) -> Vec { + vec![$($v,)*] + } + } + }; +} + +make_arrays!(2, [_a]); +make_arrays!(3, [_a, _b]); +make_arrays!(4, [_a, _b, _c]); +make_arrays!(5, [_a, _b, _c, _d]); +make_arrays!(6, [_a, _b, _c, _d, _e]); +make_arrays!(7, [_a, _b, _c, _d, _e, _g]);