coremem_types: list: switch to parameter-based indexing; add apply method

This commit is contained in:
2022-07-20 14:31:20 -07:00
parent e029c8b3d9
commit d0ae25e28b

View File

@@ -154,24 +154,30 @@ impl<Output, F> ListOp<F, Null, Output> for Null {
} }
} }
pub trait SameType<T> { }
impl<T> SameType<T> for T { }
/// implemented on a list AND index, allowing potentially non-generic code to fetch a /// implemented on a list AND index, allowing potentially non-generic code to fetch a
/// compile-time-constant element. /// compile-time-constant element.
trait IndexOp<List, Index, Elem> { pub trait IndexOp<List, Index, Elem> {
// TODO: would be nice to make idx a fn parameter fn apply<I: SameType<Index>, R, F: Fn(&Elem) -> R>(&self, f: F) -> R;
fn get(&self, idx: Index) -> &Elem; fn get<I: SameType<Index>>(&self) -> &Elem;
fn get_mut(&mut self, idx: Index) -> &mut Elem; fn get_mut<I: SameType<Index>>(&mut self) -> &mut Elem;
fn set(&mut self, idx: Index, el: Elem) { fn set<I: SameType<Index>>(&mut self, el: Elem) {
*self.get_mut(idx) = el; *self.get_mut::<I>() = el;
} }
} }
/// zero-index into Self /// zero-index into Self
impl<H, T> IndexOp<Node<H, T>, P0, H> for Node<H, T> impl<H, T> IndexOp<Node<H, T>, P0, H> for Node<H, T>
{ {
fn get(&self, _idx: P0) -> &H { fn apply<I: SameType<P0>, R, F: Fn(&H) -> R>(&self, f: F) -> R {
f(&self.head)
}
fn get<I: SameType<P0>>(&self) -> &H {
&self.head &self.head
} }
fn get_mut(&mut self, _idx: P0) -> &mut H { fn get_mut<I: SameType<P0>>(&mut self) -> &mut H {
&mut self.head &mut self.head
} }
} }
@@ -182,11 +188,14 @@ where
P: Peano, P: Peano,
T: IndexOp<T, P, ElemAtP> T: IndexOp<T, P, ElemAtP>
{ {
fn get(&self, _idx: PNext<P>) -> &ElemAtP { fn apply<I: SameType<PNext<P>>, R, F: Fn(&ElemAtP) -> R>(&self, f: F) -> R {
self.tail.get(P::default()) self.tail.apply::<P, R, F>(f)
} }
fn get_mut(&mut self, _idx: PNext<P>) -> &mut ElemAtP { fn get<I: SameType<PNext<P>>>(&self) -> &ElemAtP {
self.tail.get_mut(P::default()) self.tail.get::<P>()
}
fn get_mut<I: SameType<PNext<P>>>(&mut self) -> &mut ElemAtP {
self.tail.get_mut::<P>()
} }
} }
@@ -332,27 +341,27 @@ mod test {
let list = Node::new_terminal(3f32) let list = Node::new_terminal(3f32)
.prepend(4i32) .prepend(4i32)
.prepend(5u32); .prepend(5u32);
assert_eq!(list.get(P0), &5u32); assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get(P1::default()), &4i32); assert_eq!(list.get::<P1>(), &4i32);
assert_eq!(list.get(P2::default()), &3f32); assert_eq!(list.get::<P2>(), &3f32);
} }
#[test] #[test]
fn set() { fn set() {
let mut list = List::<(u32, i32, f32)>::default(); let mut list = List::<(u32, i32, f32)>::default();
list.set(P0, 5u32); list.set::<P0>(5u32);
assert_eq!(list.get(P0), &5u32); assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get(P1::default()), &0i32); assert_eq!(list.get::<P1>(), &0i32);
assert_eq!(list.get(P2::default()), &0f32); assert_eq!(list.get::<P2>(), &0f32);
list.set(P2::default(), 3f32); list.set::<P2>(3f32);
list.set(P1::default(), 4i32); list.set::<P1>(4i32);
assert_eq!(list.get(P0), &5u32); assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get(P1::default()), &4i32); assert_eq!(list.get::<P1>(), &4i32);
assert_eq!(list.get(P2::default()), &3f32); assert_eq!(list.get::<P2>(), &3f32);
} }
#[test] #[test]
@@ -369,8 +378,8 @@ mod test {
fn test_into_list() { fn test_into_list() {
let list = (5u32, 4i32, 3f32).into_list(); let list = (5u32, 4i32, 3f32).into_list();
assert_eq!(list.get(P0), &5u32); assert_eq!(list.get::<P0>(), &5u32);
assert_eq!(list.get(P1::default()), &4i32); assert_eq!(list.get::<P1>(), &4i32);
assert_eq!(list.get(P2::default()), &3f32); assert_eq!(list.get::<P2>(), &3f32);
} }
} }