diff --git a/src/lenses/first_tuple.rs b/src/lenses/first.rs similarity index 76% rename from src/lenses/first_tuple.rs rename to src/lenses/first.rs index d7b2e30..b029304 100644 --- a/src/lenses/first_tuple.rs +++ b/src/lenses/first.rs @@ -2,7 +2,7 @@ use crate::{LensOver, LensView}; pub struct _0; -macro_rules! make { +macro_rules! make_tuples { ($f:ident, ( $( $v:ident ),* ), ( $( $t:ident ),* ) ) => { impl< $($t,)* > LensView<( $($t,)* )> for _0 { type Field = T; @@ -11,7 +11,6 @@ macro_rules! make { $f } } - impl< $($t,)* > LensOver<( $($t,)* )> for _0 { fn over( mut tup: ($($t,)*), @@ -21,6 +20,7 @@ macro_rules! make { tup } } + impl<'a, $($t,)* > LensView<&'a ( $($t,)* )> for _0 { type Field = &'a T; @@ -38,10 +38,10 @@ macro_rules! make { }; } -make!(t, (t, _u), (T, U)); -make!(t, (t, _u, _v), (T, U, V)); -make!(t, (t, _u, _v, _w), (T, U, V, W)); -make!(t, (t, _u, _v, _w, _x), (T, U, V, W, X)); -make!(t, (t, _u, _v, _w, _x, _y), (T, U, V, W, X, Y)); -make!(t, (t, _u, _v, _w, _x, _y, _z), (T, U, V, W, X, Y, Z)); +make_tuples!(t, (t, _u), (T, U)); +make_tuples!(t, (t, _u, _v), (T, U, V)); +make_tuples!(t, (t, _u, _v, _w), (T, U, V, W)); +make_tuples!(t, (t, _u, _v, _w, _x), (T, U, V, W, X)); +make_tuples!(t, (t, _u, _v, _w, _x, _y), (T, U, V, W, X, Y)); +make_tuples!(t, (t, _u, _v, _w, _x, _y, _z), (T, U, V, W, X, Y, Z)); // not doing more cause i'm lazy, open a pr if you need more :) diff --git a/src/lenses/id.rs b/src/lenses/id.rs new file mode 100644 index 0000000..c8ef6e1 --- /dev/null +++ b/src/lenses/id.rs @@ -0,0 +1,17 @@ +use crate::{LensOver, LensView}; + +#[allow(non_camel_case_types)] +pub struct id; + +impl LensView for T { + type Field = T; + + fn view(thing: T) -> Self::Field { + thing + } +} +impl LensOver for T { + fn over(thing: T, f: &dyn Fn(Self::Field) -> Self::Field) -> T { + f(thing) + } +} diff --git a/src/lenses/mod.rs b/src/lenses/mod.rs index 42052fd..509ae4a 100644 --- a/src/lenses/mod.rs +++ b/src/lenses/mod.rs @@ -1,2 +1,4 @@ -mod first_tuple; -pub use first_tuple::_0; +mod id; +pub use id::id; +mod first; +pub use first::_0; diff --git a/src/lib.rs b/src/lib.rs index d382d15..92cb510 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,11 +6,18 @@ pub trait LensView { pub trait LensOver: LensView { fn over(thing: T, f: &dyn Fn(Self::Field) -> Self::Field) -> T; + + fn set(thing: T, v: Self::Field) -> T { + Self::over(thing, &|_| v) + } } pub fn view>(_lens: L, thing: T) -> L::Field { L::view(thing) } +pub fn set>(_lens: L, thing: T, v: L::Field) -> T { + L::set(thing, v) +} pub fn over>(_lens: L, thing: T, f: &dyn Fn(L::Field) -> L::Field) -> T { L::over(thing, f) } @@ -19,6 +26,12 @@ pub fn over>(_lens: L, thing: T, f: &dyn Fn(L::Field) -> L::Fi // with one param it should be view, with two it should be over // TODO add std::ops::Add to combine lenses +// TODO add second_from_tuple, etc + +// TODO array traversals + +// TODO make over work with changing types + pub mod lenses; #[cfg(test)] @@ -56,7 +69,18 @@ mod tests { } #[test] - fn over_first_from_tuple_mut_works() { + fn set_first_from_tuple() { + let a = (1, 2); + let a = set(_0, a, 3); + assert_eq!(a, (3, 2)); + + let a = (1, 2); + let a = _0::set(a, 3); + assert_eq!(a, (3, 2)); + } + + #[test] + fn over_first_from_tuple() { let a = (1, 2); let a = over(_0, a, &|v| v + 1); assert_eq!(a, (2, 2));