Skip to content

Commit

Permalink
Merge pull request #20 from calcit-lang/traverse
Browse files Browse the repository at this point in the history
traverse methods
  • Loading branch information
NoEgAm authored Feb 27, 2024
2 parents 6462f88 + 1574bca commit efbbf2f
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 8 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

[package]
name = "im_ternary_tree"
version = "0.0.17"
version = "0.0.18"
edition = "2021"
authors = ["jiyinyiyong <jiyinyiyong@gmail.com>"]
license = "MIT"
Expand All @@ -23,7 +23,7 @@ criterion = "0.3"


[[bench]]
name = "accessing"
name = "iterator"
harness = false

[profile.release]
Expand Down
36 changes: 36 additions & 0 deletions benches/iterator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use criterion::{criterion_group, criterion_main, Criterion};

use im_ternary_tree::TernaryTreeList;

const ITER_SIZE: usize = 10000;

fn criterion_benchmark(c: &mut Criterion) {
let mut data = TernaryTreeList::Empty;

for idx in 0..ITER_SIZE {
data = data.push(idx)
}

c.bench_function("iter", |b| {
let mut cc = 0;

b.iter(|| {
for item in &data {
cc += item;
}
})
});

c.bench_function("traverse", |b| {
let mut cc = 0;

b.iter(|| {
data.traverse(&mut |item| {
cc += item;
});
})
});
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
17 changes: 17 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,23 @@ where
}
}

/// traverse all elements in list, use referenced value
pub fn traverse(&self, f: &mut dyn FnMut(&T)) {
match self {
Empty => (),
Tree(t) => t.traverse(f),
}
}

/// traverse elements in list, use referenced value,
/// returns `Ok` when all elements are traversed
pub fn traverse_result<S>(&self, f: &mut dyn FnMut(&T) -> Result<(), S>) -> Result<(), S> {
match self {
Empty => Ok(()),
Tree(t) => t.traverse_result(f),
}
}

pub fn iter(&self) -> TernaryTreeListRefIntoIterator<T> {
TernaryTreeListRefIntoIterator {
value: self,
Expand Down
44 changes: 38 additions & 6 deletions src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1240,8 +1240,40 @@ where
xs
}

pub fn iter(&self) -> TernaryTreeRefIntoIterator<T> {
TernaryTreeRefIntoIterator {
pub fn traverse(&self, f: &mut dyn FnMut(&T)) {
match self {
Leaf(value) => f(value),
Branch2 { left, middle, .. } => {
left.traverse(f);
middle.traverse(f);
}
Branch3 { left, middle, right, .. } => {
left.traverse(f);
middle.traverse(f);
right.traverse(f);
}
}
}

pub fn traverse_result<S>(&self, f: &mut dyn FnMut(&T) -> Result<(), S>) -> Result<(), S> {
match self {
Leaf(value) => f(value),
Branch2 { left, middle, .. } => {
left.traverse_result(f)?;
middle.traverse_result(f)?;
Ok(())
}
Branch3 { left, middle, right, .. } => {
left.traverse_result(f)?;
middle.traverse_result(f)?;
right.traverse_result(f)?;
Ok(())
}
}
}

pub fn iter(&self) -> TernaryTreeIterator<T> {
TernaryTreeIterator {
value: self,
index: 0,
size: self.len(),
Expand All @@ -1268,24 +1300,24 @@ where
T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash,
{
type Item = &'a T;
type IntoIter = TernaryTreeRefIntoIterator<'a, T>;
type IntoIter = TernaryTreeIterator<'a, T>;

fn into_iter(self) -> Self::IntoIter {
TernaryTreeRefIntoIterator {
TernaryTreeIterator {
value: self,
index: 0,
size: self.len(),
}
}
}

pub struct TernaryTreeRefIntoIterator<'a, T> {
pub struct TernaryTreeIterator<'a, T> {
value: &'a TernaryTree<T>,
index: usize,
size: usize,
}

impl<'a, T> Iterator for TernaryTreeRefIntoIterator<'a, T>
impl<'a, T> Iterator for TernaryTreeIterator<'a, T>
where
T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash,
{
Expand Down
64 changes: 64 additions & 0 deletions tests/list_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,27 @@ fn iterator() -> Result<(), String> {
Ok(())
}

#[test]
fn iter_enum() -> Result<(), String> {
let origin4 = [1, 2, 3, 4];
let data4 = TernaryTreeList::from(&origin4);

let mut i = 0;
for _ in &data4 {
i += 1;
}

assert_eq!(i, 4);

i = 0;
for (idx, _) in data4.iter().enumerate() {
i += idx;
assert_eq!(data4.loop_get(idx).unwrap(), &origin4[idx]);
}

Ok(())
}

#[test]
fn check_structure() -> Result<(), String> {
let mut data = TernaryTreeList::from(&[]);
Expand Down Expand Up @@ -462,3 +483,46 @@ fn split_values() -> Result<(), String> {

Ok(())
}

#[test]
fn traverse() -> Result<(), String> {
let n = 100;
let mut data = TernaryTreeList::from(&[]);
let mut total = 0;
for idx in 0..n {
data = data.append(idx);
total += idx;
}

let mut c = 0;

data.traverse(&mut |x| {
c += x;
});

assert_eq!(c, total);

Ok(())
}

#[test]
fn traverse_result() -> Result<(), String> {
let n = 100;
let mut data = TernaryTreeList::from(&[]);
let mut total = 0;
for idx in 0..n {
data = data.append(idx);
total += idx;
}

let mut c = 0;

data.traverse_result::<String>(&mut |x| {
c += x;
Ok(())
})?;

assert_eq!(c, total);

Ok(())
}

0 comments on commit efbbf2f

Please sign in to comment.