Skip to content

Instantly share code, notes, and snippets.

@burg
Created October 13, 2012 22:22
Show Gist options
  • Save burg/3886401 to your computer and use it in GitHub Desktop.
Save burg/3886401 to your computer and use it in GitHub Desktop.
tree fail
use core::vec;
// A generic tree datatype.
mod tree {
pub type Tree<T> = {
mut parent: Option<T>,
mut first_child: Option<T>,
mut last_child: Option<T>,
mut prev_sibling: Option<T>,
mut next_sibling: Option<T>
};
pub trait TreeNodeOps<T> {
fn with_tree_fields<R>(cb: fn(&Tree<T>) -> R) -> R;
}
pub fn each_child<T:Copy TreeNodeOps<T>>(node: &T, f: fn(&T) -> bool) {
let mut p = node.with_tree_fields(|f| f.first_child);
loop {
match copy p {
None => { return; }
Some(ref c) => {
if !f(c) { return; }
p = node.with_tree_fields(|f| f.next_sibling);
}
}
}
}
pub fn empty<T>() -> Tree<T> {
{mut parent: None,
mut first_child: None,
mut last_child: None,
mut prev_sibling: None,
mut next_sibling: None}
}
pub fn add_child<T:Copy TreeNodeOps<T>>(parent: T, child: T) {
child.with_tree_fields(|child_tf| {
match child_tf.parent {
Some(_) => { fail ~"Already has a parent"; }
None => { child_tf.parent = Some(parent); }
}
assert child_tf.prev_sibling.is_none();
assert child_tf.next_sibling.is_none();
parent.with_tree_fields(|parent_tf| {
match copy parent_tf.last_child {
None => {
parent_tf.first_child = Some(child);
}
Some(lc) => {
do lc.with_tree_fields |lc_tf| {
assert lc_tf.next_sibling.is_none();
lc_tf.next_sibling = Some(child);
}
child_tf.prev_sibling = Some(lc);
}
}
parent_tf.last_child = Some(child);
});
});
}
}
struct dummy {
fields: tree::Tree<@dummy>,
value: uint
}
impl dummy : tree::TreeNodeOps<@dummy> {
fn with_tree_fields<R>(f: fn(&tree::Tree<@dummy>) -> R) -> R {
f(&self.fields)
}
}
fn new_dummy(v: uint) -> @dummy {
@dummy { fields: tree::empty(), value: v }
}
fn parent_with_3_children() -> {p: @dummy, children: ~[@dummy]} {
let children = ~[new_dummy(0u),
new_dummy(1u),
new_dummy(2u)];
let p : @dummy = new_dummy(3u);
for vec::each(children) |c: &@dummy| {
// ERROR: failed to find an implementation of trait @tree::TreeNodeOps<<V7>> for <V7>
tree::add_child(p, *c);
// ^~~~~~~~~~~~~~~
}
return {p: p, children: children};
}
fn add_child_0() {
let {p, children} = parent_with_3_children();
let mut i = 0u;
for tree::each_child(p) |c: &@dummy| {
// ERROR: mismatched types: expected `fn&(&dummy)` but found `fn&(&@dummy)` (expected class dummy but found @-ptr)
assert c.value == i;
i += 1u;
}
assert i == children.len();
}
fn main() {
add_child_0();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment