1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
//! # Overview //! //! `lens-rs` is a lens library for Rust, just like the package [`lens`](https://hackage.haskell.org/package/lens) for Haskell, //! but here are no weird operators, grotesque symbols and confusing types. //! Not only can `lens-rs` get/set for fields of struct, but also variants of enum and items of collection. //! It unifies the way to access to/construct with different nested substructures, providing Rusty-APIs. //! //! //! //! ## Before use //! //! Add the following in your Cargo.toml //! //! ```toml //! [dependencies] //! lens-rs = "0.2" //! //! [package.metadata.inwelling] //! lens-rs = true //! ``` //! //! Add the following in your .rs files //! //! ```rust //! use lens_rs::*; //! ``` //! //! //! ## Usage //! //! ## Access substructures //! //! visit field in struct: //! //! ```rust //! let mut x = Foo { a: String::from(".a in Foo"), b: 0 }; //! assert_eq!(x.view_ref(optics!(a)), ".a in Foo"); //! //! *x.view_mut(optics!(b)) += 1; //! assert_eq!(x.view_ref(optics!(b)), &1) //! ``` //! //! visit variant in enum: //! //! ```rust //! let mut x = Ok(0); //! *x.preview_ref(optics!(Ok))? += 1; //! assert_eq!(x.preview_ref(optics!(Ok))?, &1); //! assert_eq!(x.preview_ref(optics!(Err)), None); //! ``` //! //! visit items in collection: //! //! ```rust //! let mut x = vec![1, 2, 3]; //! x.traverse_mut(optics!(_mapped)).into_iter().for_each(|x| *x += 1); //! assert_eq!(x.traverse_ref(optics!(_mapped)), vec![&2, &3, &4]); //! assert_eq!(x.view_ref(optics!([1])), &3); //! ``` //! //! build a structure: //! //! ```rust //! let x = Review::review(optics!(Ok.Some), 1); //! assert_eq!(x, Ok(Some(1))); //! ``` //! //! ## Compose optics //! //! macro `optics!()` and `Optics![]` is to compose optics: //! //! ```rust //! let optics: Optics![_1.a.Some._mapped.[1]] = optics!(_1.a.Some._mapped.[1]); //! //! let x = (0, Foo { //! a: Some(vec![vec![1,2], vec![3,4]]), //! b: () //! }); //! //! assert_eq!(x.traverse(optics), vec![2, 4]); //! ``` //! //! ## Derive Optics //! //! Derive Lens for fields to use `.view_xx()`. (derive(Optic) is necessary) //! //! ```rust //! #[derive(Optic, Lens)] //! struct Foo<A, B> { //! #[optic] //! a: A, // generate optics::a //! #[optic] //! b: B, // generate optics::b //! } //! //! #[derive(Optic, Lens)] //! struct Tuple<A, B>(#[optic] A, #[optic] B); //! // use optics::_0 or optics::_1 to access it //! ``` //! //! Derive Review/Prism for variants to use `Review::review`/`.preview_xx()`: //! //! ```rust //! #[derive(Optic, Review, Prism)] //! enum Either<L, R> { //! #[optic] //! Left(L), // generate optics::Left //! #[optic] //! Right(R), // generate optics::Right //! } //! ``` //! //! Control the mutability: //! //! ```rust //! #[derive(Debug, Optic, Lens)] //! struct Bar<C>{ //! #[optic(ref)] //! a: String, // can only take the immutable ref of .a by optics::a //! #[optic(mut)] //! b: i32, // can take the mutable ref of .b by optics::b //! #[optic] //! c: C // can move .c out by by optics::c //! } //! ``` //! //! ## A little row polymorphism //! //! restrict a type has some fields: //! //! ```rust //! fn with_field_a<T>(t: &T) -> &str //! where //! T: LensRef<Optics![a], Image = String>, // T must have field a //! { //! t.view_ref(optics!(a)) //! } //! //! //! let foo = Foo { //! a: "this is Foo".to_string(), //! b: (), //! }; //! let bar = Bar { //! a: "this is Bar".to_string(), //! c: 0, //! }; //! //! assert_eq!(with_field_a(&foo), "this is Foo"); //! assert_eq!(with_field_a(&bar), "this is Bar"); //! ``` //! //! # Limitations //! //! * can't derive `Lens` for enum. //! * can't derive `Prism` and `Review` for the variant has more than one argument or has named field. //! //! # License //! //! Under Apache License 2.0 or MIT License, at your will. /// definitions of optics (including derived optic) pub mod optics; /// definitions of optics traits pub mod traits; pub use traits::{lens::*, prism::*, review::*, traversal::*}; /// build-in optics pub use optics::{ _both, _box, _ix, _mapped, _mut, _ref, _0, _1, _10, _11, _12, _13, _14, _15, _16, _2, _3, _4, _5, _6, _7, _8, _9, __, }; /// derive macro pub use lens_rs_derive::{Lens, Prism, Review}; /// macro to compose optics /// /// ```rust /// let optics: Optics![a.Some.[0]._0] = optics!(a.Some.[0]._0); /// // equivalent to optics!(lens_rs::optics::a.lens_rs::optics::Some.[0].lens_rs::optics::_0) /// // the default optics path is `lens_rs::optics`. /// ``` pub use lens_rs_derive::{optics, Optics};