├── Cargo.toml ├── README.md └── src └── lib.rs /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mutation" 3 | version = "0.1.0" 4 | authors = ["Joshua Barretto "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mutation 2 | 3 | Use the power of nightly Rust to write code that's generic over mutation! 4 | 5 | # Features 6 | 7 | - Zero-cost (at runtime)! 8 | 9 | - Highly likely to trigger Internal Compiler Errors (ICE)! 10 | 11 | - A horrific type astronomy hack! 12 | 13 | - Would work even better if Rust had proper higher-kinded types instead of just GATs! 14 | 15 | - Kind of works with iterators 16 | 17 | **Highly Experimental** 18 | 19 | Are you frequently frustrated by the need to write near-identical functions that 20 | differ only by the occurrence of the `mut` keyword? 21 | 22 | Do you wish you that you didn't have to maintain two independent versions of 23 | what effectively amount to the same function? 24 | 25 | Well, your dreams probably aren't going to come true. This might be the next 26 | best thing though, assuming you're a normal person that thinks that macros are 27 | silly. 28 | 29 | ## Example 30 | 31 | ```rust 32 | use mutation::prelude::*; 33 | 34 | struct MyVec(Vec); 35 | 36 | impl MyVec { 37 | /// This function 'glues' our generic-over-mutation API to the underlying 38 | /// non-generic API of `Vec`. 39 | pub fn get<'a, R: Ref<'a, Self>>(self: R, idx: usize) -> Option> { 40 | /// The underlying `Vec` is not generic over mutation, so here we 41 | /// specialize our function with the corresponding function of `Vec`. 42 | self.map::>, _, _>( 43 | |this: &Self| this.0.get(idx), 44 | |this: &mut Self| this.0.get_mut(idx), 45 | ) 46 | } 47 | 48 | /// This function 'glues' our generic-over-mutation API to the underlying 49 | /// non-generic API of `Vec`. 50 | pub fn iter<'a, R: Ref<'a, Self>>(self: R) -> impl Iterator> where T: 'a { 51 | /// The underlying `Vec` is not generic over mutation, so here we 52 | /// specialize our function with the corresponding function of `Vec`. 53 | self.map::, _, _>( 54 | |this: &Self| this.0.iter(), 55 | |this: &mut Self| this.0.iter_mut(), 56 | ) 57 | } 58 | 59 | /// And now for some functions that are truly generic over mutation using 60 | /// the API above... 61 | 62 | /// This function works for both mutable and immutable references! 63 | pub fn get_expect<'a, R: Ref<'a, Self>>(self: R, idx: usize) -> RefMap<'a, R, T> { 64 | self.get(idx).unwrap() 65 | } 66 | 67 | /// This function works for both mutable and immutable references! 68 | pub fn iter_positive<'a, R: Ref<'a, Self>>(self: R) -> impl Iterator> 69 | where T: PartialOrd + 'a 70 | { 71 | self.iter().filter(|x| **x >= 0) 72 | } 73 | } 74 | 75 | /// Example usage 76 | 77 | let mut my_vec = MyVec(vec![1, 2, 3]); 78 | 79 | assert_eq!((&my_vec).iter().copied().sum::(), 8); 80 | 81 | // Iterate elements immutably 82 | assert_eq!((&my_vec).iter_positive().copied().sum::(), 9); 83 | 84 | // Mutate the second element 85 | *(&mut my_vec).get_expect(1) = 4; 86 | 87 | // Immutably access the second element 88 | assert_eq!(my_vec.get_expect(1), Some(&4)); 89 | 90 | // Iterate elements mutably, giving each a value of 1 91 | (&mut my_vec).iter_positive().for_each(|x| *x = 1); 92 | 93 | assert_eq!(my_vec.0, vec![-1, 1, 1, 1]); 94 | ``` 95 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(generic_associated_types, arbitrary_self_types, trait_alias)] 2 | 3 | use core::ops::Deref; 4 | 5 | pub trait IsRef<'a> { 6 | type Inner: 'a; 7 | type Mut: Mut; 8 | type Map where B: 'a; 9 | 10 | fn map, F, G>( 11 | self, 12 | f: F, 13 | g: G, 14 | ) -> B::Ty<'a, Self::Mut> 15 | where 16 | F: FnOnce(&'a Self::Inner) -> B::Ty<'a, Immutable>, 17 | G: FnOnce(&'a mut Self::Inner) -> B::Ty<'a, Mutable>; 18 | } 19 | 20 | impl<'a, T> IsRef<'a> for &'a T { 21 | type Inner = T; 22 | type Mut = Immutable; 23 | type Map where B: 'a = &'a B; 24 | 25 | fn map, F, G>( 26 | self, 27 | f: F, 28 | g: G, 29 | ) -> B::Ty<'a, Self::Mut> 30 | where 31 | F: FnOnce(&'a Self::Inner) -> B::Ty<'a, Immutable>, 32 | G: FnOnce(&'a mut Self::Inner) -> B::Ty<'a, Mutable> 33 | { 34 | f(self) 35 | } 36 | } 37 | 38 | impl<'a, T> IsRef<'a> for &'a mut T { 39 | type Inner = T; 40 | type Mut = Mutable; 41 | type Map where B: 'a = &'a mut B; 42 | 43 | fn map, F, G>( 44 | self, 45 | f: F, 46 | g: G, 47 | ) -> B::Ty<'a, Self::Mut> 48 | where 49 | F: FnOnce(&'a Self::Inner) -> B::Ty<'a, Immutable>, 50 | G: FnOnce(&'a mut Self::Inner) -> B::Ty<'a, Mutable> 51 | { 52 | g(self) 53 | } 54 | } 55 | 56 | pub trait GenMut<'g> { 57 | type Ty<'a, M: Mut> where 'g: 'a; 58 | } 59 | 60 | pub struct GenRef<'a, T>(&'a T); 61 | 62 | impl<'g, T: 'g> GenMut<'g> for GenRef<'g, T> { 63 | type Ty<'b, M: Mut> where 'g: 'b = M::Ref<'b, T>; 64 | } 65 | 66 | impl<'g, T: GenMut<'g>> GenMut<'g> for Option { 67 | type Ty<'b, M: Mut> where 'g: 'b = Option>; 68 | } 69 | 70 | pub struct SliceIter<'a, T>(&'a T); 71 | 72 | impl<'g, T: 'g> GenMut<'g> for SliceIter<'g, T> { 73 | type Ty<'b, M: Mut> where 'g: 'b = M::SliceIter<'b, T>; 74 | } 75 | 76 | pub trait Mut: Sized { 77 | type Ref<'a, T>: Deref where T: 'a; 78 | type SliceIter<'a, T>: Iterator> where T: 'a; 79 | } 80 | 81 | pub struct Immutable; 82 | impl Mut for Immutable { 83 | type Ref<'a, T> where T: 'a = &'a T; 84 | type SliceIter<'a, T> where T: 'a = core::slice::Iter<'a, T>; 85 | } 86 | 87 | pub struct Mutable; 88 | impl Mut for Mutable { 89 | type Ref<'a, T> where T: 'a = &'a mut T; 90 | type SliceIter<'a, T> where T: 'a = core::slice::IterMut<'a, T>; 91 | } 92 | 93 | pub trait Ref<'a, T> = IsRef<'a, Inner = T> + Deref; 94 | 95 | pub type RefMap<'a, R, T> = as GenMut<'a>>::Ty<'a, >::Mut>; 96 | 97 | pub struct MyVec(Vec); 98 | 99 | impl MyVec { 100 | pub fn get<'a, R: Ref<'a, Self>>(self: R, idx: usize) -> Option> { 101 | self.map::>, _, _>( 102 | |this: &Self| this.0.get(idx), 103 | |this: &mut Self| this.0.get_mut(idx), 104 | ) 105 | } 106 | 107 | pub fn get_expect<'a, R: Ref<'a, Self>>(self: R, idx: usize) -> RefMap<'a, R, T> { 108 | self.get(idx).unwrap() 109 | } 110 | 111 | pub fn iter<'a, R: Ref<'a, Self>>(self: R) -> impl Iterator> where T: 'a { 112 | self.map::, _, _>( 113 | |this: &Self| this.0.iter(), 114 | |this: &mut Self| this.0.iter_mut(), 115 | ) 116 | } 117 | 118 | pub fn iter_positive<'a, R: Ref<'a, Self>>(self: R) -> impl Iterator> 119 | where T: PartialOrd + 'a 120 | { 121 | self.iter().filter(|x| **x >= 0) 122 | } 123 | } 124 | 125 | #[test] 126 | fn basic() { 127 | let mut x = MyVec(vec![-1, 2, 3, 4]); 128 | 129 | assert_eq!((&x).iter().copied().sum::(), 8); 130 | 131 | assert_eq!((&x).iter_positive().copied().sum::(), 9); 132 | 133 | *(&mut x).get(1).unwrap() = 3; 134 | assert_eq!(*x.get_expect(1), 3); 135 | 136 | (&mut x).iter_positive().for_each(|x| *x = 1); 137 | 138 | assert_eq!(x.0, vec![-1, 1, 1, 1]); 139 | } 140 | --------------------------------------------------------------------------------