fns, example, copy, readme

main
annieversary 2021-11-05 14:22:59 +00:00
parent 4a4751dcb2
commit c00229da08
8 changed files with 154 additions and 2 deletions

39
README.md Normal file
View File

@ -0,0 +1,39 @@
# bad optics
ergonomic no-macro lenses for rust
## example
```rust
use bad_optics::{
lenses::{_0, _1},
*,
};
fn main() {
let a = ((1, 2), 3);
// combine lenses
let lens = _0 + _1;
// use the view function to access
let res = view(lens, a);
assert_eq!(res, 2);
// call the lens as a function
let res = lens(a);
assert_eq!(res, 2);
// call the over function to modify the value
let a = over(lens, a, |v| v + 1);
assert_eq!(a, ((1, 3), 3));
// call the set function to set the value
let a = set(lens, a, 5);
assert_eq!(a, ((1, 5), 3));
// call the lens as a function to modify the value
let res = lens(a, |v| v + 1);
assert_eq!(res, ((1, 3), 3));
}
```

31
examples/main.rs Normal file
View File

@ -0,0 +1,31 @@
use bad_optics::{
lenses::{_0, _1},
*,
};
fn main() {
let a = ((1, 2), 3);
// combine lenses
let lens = _0 + _1;
// use the view function to access
let res = view(lens, a);
assert_eq!(res, 2);
// call the lens as a function
let res = lens(a);
assert_eq!(res, 2);
// call the over function to modify the value
let a = over(lens, a, |v| v + 1);
assert_eq!(a, ((1, 3), 3));
// call the set function to set the value
let a = set(lens, a, 5);
assert_eq!(a, ((1, 5), 3));
// call the lens as a function to modify the value
let res = lens(a, |v| v + 1);
assert_eq!(res, ((1, 3), 3));
}

View File

@ -1,5 +1,6 @@
use crate::{Lens, LensOver, LensTrait, LensView}; use crate::{Lens, LensOver, LensTrait, LensView};
#[derive(Clone, Copy)]
pub struct Combination<A, B>(A, B); pub struct Combination<A, B>(A, B);
impl<A, B> LensTrait for Combination<A, B> {} impl<A, B> LensTrait for Combination<A, B> {}

58
src/fns.rs Normal file
View File

@ -0,0 +1,58 @@
use crate::{Lens, LensOver, LensView};
impl<L, A> std::ops::FnOnce<(A,)> for Lens<L>
where
L: LensView<A>,
{
type Output = L::Field;
extern "rust-call" fn call_once(self, args: (A,)) -> Self::Output {
L::view(args.0)
}
}
impl<L, A> std::ops::FnMut<(A,)> for Lens<L>
where
L: LensView<A>,
{
extern "rust-call" fn call_mut(&mut self, args: (A,)) -> Self::Output {
L::view(args.0)
}
}
impl<L, A> std::ops::Fn<(A,)> for Lens<L>
where
L: LensView<A>,
{
extern "rust-call" fn call(&self, args: (A,)) -> Self::Output {
L::view(args.0)
}
}
impl<L, A, F> std::ops::FnOnce<(A, F)> for Lens<L>
where
L: LensOver<A>,
F: FnOnce(L::Field) -> L::Field,
{
type Output = A;
extern "rust-call" fn call_once(self, args: (A, F)) -> Self::Output {
L::over(args.0, args.1)
}
}
impl<L, A, F> std::ops::FnMut<(A, F)> for Lens<L>
where
L: LensOver<A>,
F: FnOnce(L::Field) -> L::Field,
{
extern "rust-call" fn call_mut(&mut self, args: (A, F)) -> Self::Output {
L::over(args.0, args.1)
}
}
impl<L, A, F> std::ops::Fn<(A, F)> for Lens<L>
where
L: LensOver<A>,
F: FnOnce(L::Field) -> L::Field,
{
extern "rust-call" fn call(&self, args: (A, F)) -> Self::Output {
L::over(args.0, args.1)
}
}

View File

@ -1,5 +1,6 @@
use crate::{Lens, LensOver, LensTrait, LensView}; use crate::{Lens, LensOver, LensTrait, LensView};
#[derive(Clone, Copy)]
pub struct _0Inner; pub struct _0Inner;
pub const _0: Lens<_0Inner> = Lens(_0Inner); pub const _0: Lens<_0Inner> = Lens(_0Inner);
impl LensTrait for _0Inner {} impl LensTrait for _0Inner {}

View File

@ -1,6 +1,7 @@
use crate::{LensOver, LensTrait, LensView}; use crate::{LensOver, LensTrait, LensView};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub struct id; pub struct id;
impl LensTrait for id {} impl LensTrait for id {}

View File

@ -1,5 +1,6 @@
use crate::{Lens, LensOver, LensTrait, LensView}; use crate::{Lens, LensOver, LensTrait, LensView};
#[derive(Clone, Copy)]
pub struct _1Inner; pub struct _1Inner;
pub const _1: Lens<_1Inner> = Lens(_1Inner); pub const _1: Lens<_1Inner> = Lens(_1Inner);
impl LensTrait for _1Inner {} impl LensTrait for _1Inner {}

View File

@ -1,3 +1,5 @@
#![feature(unboxed_closures, fn_traits)]
/// Base trait /// Base trait
pub trait LensTrait {} pub trait LensTrait {}
@ -20,6 +22,7 @@ pub trait LensOver<T>: LensView<T> {
} }
/// Wrapper type /// Wrapper type
#[derive(Clone, Copy)]
pub struct Lens<T: LensTrait>(T); pub struct Lens<T: LensTrait>(T);
impl<L: LensTrait> LensTrait for Lens<L> {} impl<L: LensTrait> LensTrait for Lens<L> {}
@ -55,8 +58,6 @@ pub fn over<T, L: LensOver<T>>(_lens: L, thing: T, f: impl FnOnce(L::Field) -> L
L::over(thing, f) L::over(thing, f)
} }
mod combinations;
// TODO add fn impls // TODO add fn impls
// TODO add third_from_tuple, etc // TODO add third_from_tuple, etc
@ -65,6 +66,8 @@ mod combinations;
// TODO make over work with changing types // TODO make over work with changing types
mod combinations;
mod fns;
pub mod lenses; pub mod lenses;
#[cfg(test)] #[cfg(test)]
@ -150,4 +153,21 @@ mod tests {
let a = over(lens, a, |v| v + 1); let a = over(lens, a, |v| v + 1);
assert_eq!(a, ((1, 3), 3)); assert_eq!(a, ((1, 3), 3));
} }
#[test]
fn call_as_funcs() {
let a = (1, 2);
assert_eq!(_0(a), 1);
let a = (1, 2);
assert_eq!(_0(a, |v| v + 1), (2, 2));
let a = ((1, 2), 3);
let lens = _0 + _1;
let res = lens(a);
assert_eq!(res, 2);
let res = lens(a, |v| v + 1);
assert_eq!(res, ((1, 3), 3));
}
} }