coremem_types: List: add an apply_at method

This commit is contained in:
2022-07-20 01:57:19 -07:00
parent f8930fd6ea
commit a56cdabf5e

View File

@@ -31,6 +31,12 @@ impl<E, N> LLNode<E, N> {
trait ListOp<F, L> {
/// apply `f` to all elements in the list.
fn apply(&self, f: F);
/// apply `f` *only* to the element at the provided index
fn apply_at(&self, i: u32, f: F) {
self.apply_at_rel(i, 0, f);
}
// helper: tracks the current index into the list to know when to call `f`
fn apply_at_rel(&self, i: u32, cur: u32, f: F);
}
/// some operation which can be applied to the provided element type `T`.
@@ -46,12 +52,24 @@ impl<F: ElementOp<E>, E, N: ListOp<F, N>> ListOp<F, LLNode<E, N>> for LLNode<E,
// apply the operation to all tail elements
self.next.apply(f)
}
fn apply_at_rel(&self, i: u32, cur: u32, f: F) {
if i == cur {
f.call(&self.e)
}
self.next.apply_at_rel(i, cur + 1, f);
}
}
impl<F> ListOp<F, Null> for Null {
fn apply(&self, _f: F) {
// the tail element simply terminates recursion
}
fn apply_at_rel(&self, i: u32, cur: u32, _f: F) {
if i >= cur {
// if the requested index was past the length of the list, undef
unreachable!();
}
}
}
#[cfg(test)]
@@ -144,6 +162,27 @@ mod test {
assert_eq!(acc.delayed2.into_inner(), V0(2u32).to_flat());
assert_eq!(acc.delayed1.into_inner(), V1(4f32).to_flat());
assert_eq!(acc.delayed0.into_inner(), V0(5u32).to_flat());
}
#[test]
fn test_apply_at() {
let list = LLNode::new(V0(5u32))
.prepend(V1(4f32))
.prepend(V0(2u32));
let acc = ApplyAccumulator::default();
list.apply_at(0, &acc);
assert_eq!(acc.delayed0.into_inner(), V0(2u32).to_flat());
assert_eq!(acc.delayed1.into_inner(), Flat::default());
let acc = ApplyAccumulator::default();
list.apply_at(1, &acc);
assert_eq!(acc.delayed0.into_inner(), V1(4f32).to_flat());
assert_eq!(acc.delayed1.into_inner(), Flat::default());
let acc = ApplyAccumulator::default();
list.apply_at(2, &acc);
assert_eq!(acc.delayed0.into_inner(), V0(5u32).to_flat());
assert_eq!(acc.delayed1.into_inner(), Flat::default());
}
}