S.E.A.N.I.C.U.S.

Friday, April 28, 2006

Do not underestimate the power of the block side!

I discovered some powerful things you can do with blocks this week. Specifically, they make recursive calling patterns very powerful. Case in point: I needed a way to traverse a tree structure BACKWARDS toward the root from the child. Since trees are hierarchical data structures, a recursive method seemed the best. However, as I found in the "Richer Helpers" post, I needed to wrap the contents of caller in the callee -- effectively flipping the recursive calling pattern on its head; that is, using Builder::XmlMarkup, the parent would be at a higher structural level than the child, like so:
xml.root {
xml.parent {
xml.child
}
}

Here's the rub: we don't know how deep in the tree the child node is, nor should we have to! Here's a basic outline of what I came up with:
def xml_tree(node, xml, &block)
if node.has_parent?
xml_tree(node.parent, xml) do
if block_given?
xml.node(:attr => node.attr){
yield
}
else
xml.node(:attr => node.attr)
end
end
else
if block_given?
xml.node(:attr => node.attr){
yield
}
else
xml.node(:attr => node.attr)
end
end
end


Thus, given your starting point node, anywhere in the tree, it will traverse backwards up to the root of the tree, nesting each level in the traversal. I will want to refine this algorithm, consolidating the cases, probably with a Proc.

Dynamic languages rule.