Home > Software design >  How to create a circular reference in Scala?
How to create a circular reference in Scala?

Time:03-31

Given the following code example

case class Thing(
    value: String,
    parents: Seq[Thing],
    children: Seq[Thing],
  )

val x = Thing(
    value = "foo",
    parents = Seq(y),
    children = Seq(),
)

val y = Thing(
    value = "bar",
    parents = Seq(x),
    children = Seq(),
)

errors out because y is not initialized when creating x, is there any way of performing this "circular referencing" without using a secondary data structure such as a hash map to manually create pointers to each object?

CodePudding user response:

One way to fix the compile code and the runtime exception is:

class Thing(
  _value: => String,
  _parents: => Seq[Thing],
  _children: => Seq[Thing]
) {
  lazy val value = _value
  lazy val parents = _parents
  lazy val children = _children
}

object Thing {
  def apply(
      value: => String,
      parents: => Seq[Thing],
      children: => Seq[Thing]
  ): Thing = {
    new Thing(value, parents, children)
  }
}

val x: Thing = Thing(
  value = "foo",
  parents = Seq(y),
  children = Seq()
)

val y: Thing = Thing(
  value = "bar",
  parents = Seq(x),
  children = Seq()
)

Fields used in Thing class must be evaluated lazily but since Scala prohibits using call-by-name for public class parameters I stored them in private class parameters and made them publicly accessible through public lazy vals.

  • Related