I’m trying to make a println replacement that outputs nested collections in a more readable format. This is best illustrated with an example: I’d like List(Set(Vector(1.0,1.1), Vector(0d)), Set(Vector("a", "b", "c"), Vector("x", "y"))) to be printed as
List
Set
Vector(1.0, 1.1)
Vector(0.0)
Set
Vector(a, b, c)
Vector(x, y)
This would be a lot easier without type erasure, but I’ve come up with
def rprint(a: Any, indent: Int = 0): Unit = a match {
case x: Traversable[_] =>
if (x.isEmpty)
rprint(x.toString, indent)
else x.head match {
case y: Traversable[_] => {
rprint(x.toString.takeWhile(_ != '('), indent)
x foreach {i => rprint(i, indent + 2)}
}
case y => rprint(x.toString, indent)
}
case x => println(" " * indent + x)
}
I’m struggling with getting this to work nicely with Arrays, without substantial code duplication. I’d like them to work the same as for other collections. Specifically:
-
Arrays are not
Traversable -
could convert Arrays using
genericArrayOpsto ArrayOps which isTraversableOnce, butTraversableOncedoesn’t have aheadmethod, so I can’t see how to get an element to check its type -
toStringdoesn’t work quite like other collections (use.deep)
What’s the best way to incorporate Arrays into this method, or is there a different approach that would work better?
To make it more flexible I’m defining a trait that includes utility methods and one abstract method, so that it can be used like that
Array(1,2).print:Then an implicit to make it look like
strandprintare methods ofAny:This handles arbitrary deep nesting, but won’t use multiple lines for collections that don’t contain collections – for instance that would print: