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> {
|
trait ListOp<F, L> {
|
||||||
/// apply `f` to all elements in the list.
|
/// apply `f` to all elements in the list.
|
||||||
fn apply(&self, f: F);
|
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`.
|
/// 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
|
// apply the operation to all tail elements
|
||||||
self.next.apply(f)
|
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 {
|
impl<F> ListOp<F, Null> for Null {
|
||||||
fn apply(&self, _f: F) {
|
fn apply(&self, _f: F) {
|
||||||
// the tail element simply terminates recursion
|
// 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)]
|
#[cfg(test)]
|
||||||
@@ -144,6 +162,27 @@ mod test {
|
|||||||
assert_eq!(acc.delayed2.into_inner(), V0(2u32).to_flat());
|
assert_eq!(acc.delayed2.into_inner(), V0(2u32).to_flat());
|
||||||
assert_eq!(acc.delayed1.into_inner(), V1(4f32).to_flat());
|
assert_eq!(acc.delayed1.into_inner(), V1(4f32).to_flat());
|
||||||
assert_eq!(acc.delayed0.into_inner(), V0(5u32).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