fns, example, copy, readme
parent
4a4751dcb2
commit
c00229da08
|
@ -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));
|
||||||
|
}
|
||||||
|
```
|
|
@ -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));
|
||||||
|
}
|
|
@ -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> {}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
24
src/lib.rs
24
src/lib.rs
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue