1

My question is how to iterate objects in Scala even when they are nested within objects?

object Foo {

  case object A extends FirstLevel {
    sealed trait SecondLevel
    case object A1 extends SecondLevel {
      println("you're in A1")
    }
  }

  case object B extends FirstLevel {
    sealed trait SecondLevel
    case object B1 extends SecondLevel {
      sealed trait ThirdLevel
      case object B1B extends ThirdLevel{
        println("now you're in B1B")
      }
    }
  }

}

bar(Foo.FirstLevel) foreach { f =>
  println(f{
  bar(f.SecondLevel foreach { s =>
    println(s)
    bar(s.ThirdLevel) ...
  }
}

// A, A1, B, B1, B1B... // and so on..

I've come close while going through the answer on these questions but they're only good for one level.

Community
  • 1
  • 1
goo
  • 2,230
  • 4
  • 32
  • 53

1 Answers1

0

If you hate the code containing the iterated objects' names twice, like:

object Content1 {...}
object Content2 {...}
object Content3 {...}
val iterated = Seq(Content1, Content2, Content3)

then the Macro features have to be used, and I'm not familiar with them :P Also if you need the function to be somehow typed, then please wait for another answer because it should need TypeTags that I don't think I have enough knowledge about.

Otherwise, by that I mean if anything can be the iterated objects, then have all the parents inherit some Traversable, and make a method like:

def iterateAnies(s: Any)(f: Any => Unit) {
  f(s)
  s match {
    case s: Traversable[_] => s.foreach(iterateAnies(_)(f))
    case _ =>
  }
}

If objects need to be HAS-A, then make another trait having a Traversable[_] and modify the iterateAnies method so it takes in the trait as s, have the f takes in the trait too, and the match part is gonna be upside-down:

trait HasTraversable {
  def traversable: Traversable[_]
}

def iterateAnies(s: HasTraversable)(f: HasTraversable => Unit) {
  f(s)
  s.traversable.foreach(_ match {
    case c: HasTraversable => iterateAnies(c)
    case _ => 
  })
}

With this you can print out their toString doing like:

val something: Any = ... //or HasTraversable
iterateAnies(something)(println(_.toString))
iterateAnies(something)(println(_ match {
  case s: String => "text"
  case s: Int    => "number"
  case s: _      => "idk"
)})

To keep track of the depth, add an Int parameter to both iterateAnies and f and increment the value while the process.

If nobody answers and you need it typed like iterateAnies[A], then let me know and I will do my best, but I'm pretty sure somebody's gonna answer even with Macro features :)

Ryoichiro Oka
  • 1,949
  • 2
  • 13
  • 20