I have a tree object that implements lazy depth-first-search as a TraversableView.
import collection.TraversableView
case class Node[T](label: T, ns: Node[T]*)
case class Tree[T](root: Node[T]) extends TraversableView[T, Traversable[_]] {
protected def underlying = null
def foreach[U](f: (T) => U) {
def dfs(r: Node[T]): TraversableView[T, Traversable[_]] = {
Traversable(r.label).view ++ r.ns.flatMap(dfs(_))
}
dfs(root).foreach(f)
}
}
This is appealingly concise and appears to work; however, the underlying = null method makes me nervous because I don’t understand what it means. (IntelliJ wrote that line for me.) I suppose it might be correct, because in this case there is no underlying strict representation of the tree, but I’m not sure.
Is the above code correct, or do I have to do something more with underlying?
Users of views will expect to be able to call
forceto get a strict collection. With your implementation, callingforceon a tree (or any transformation of a tree—e.g.,tree.take(10).filter(pred), etc.) will result in a null pointer exception.This may be fine with you—you’ll still be able to force evaluation using
toList, for example (although you should follow the advice in DaoWen’s comment if you go that route).The actual contents of
underlyingshould never get used, though, so there’s an easy fix—just make it an appropriately typed empty collection:Now if a user calls
tree.force, they’ll get a vector of labels, statically typed as aTraversable[T].