coremem_types: List: add an apply_at
method
This commit is contained in:
@@ -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());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user