ケースクラスを使用した双方向参照

case-class scala
ケースクラスを使用した双方向参照

ケースクラスに双方向ツリーを実装することは可能ですか? これは簡単なはずですが、私は困惑しています

case class Node(name:String, parent:Option[Node], children:List[Node])

私は子供を追加したい(そして新しいルートを取得する)-のようなもの

def addChild(n:String):Node = {
  Node(name, parent, Node(n, Some(this), Nil)::children)
}

しかし、子の「親」は、子を子としてリストするノードを参照しなくなるため、これは機能しません。 これは不変のリストとケースクラスで可能ですか?

以下の回答に基づいて

case class Node(name: String, parent: () => Option[Node], children: List[Node]) {
  def makeChild(name: String) = {
    lazy val newParent:Node = Node(this.name, this.parent, kid :: this.children)
    lazy val kid:Node = Node(name, () => Some(newParent), Nil)
    newParent
  }
}

  9  2


ベストアンサー

最近Twitterで@jamesiryに同じ質問をしました:-)。

彼の答えは:

sealed abstract class Tree[T]
case class Node[T](left : Tree[T], right : Tree[T]) extends Tree[T]
case class Leaf[T](value : T, parent : () => Tree[T]) extends Tree[T]

def make = {
   lazy val root = Node(left, right)
   lazy val left : Leaf[Int] = Leaf(1, () => root)
   lazy val right : Leaf[Int] = Leaf(2, () => root)
   root
}

9


注:ケースクラスがツリーを表すのに適したオプションであるかどうかを考えてください。

ケースクラスは値型であるため、親を返す唯一の方法は、完全なサブツリーのコピーを含む親のコピーを返すことです。 次に、たとえばその子を列挙すると、完全なサブツリーのコピーが再び取得されます。

ツリーでいくつかの置換を行いたい場合、例えば より深いレベルのノードを交換します。唯一の方法は、完全なツリーのコピーを作成し、古いツリーを破棄することです。

これはすべて少し不器用に思えますが、たとえばhttps://github.com/lift/lift/tree/master/framework/lift-base/lift-json/[lift-json]はケースクラスを使用してJSON ASTを表します。大した問題ではないかもしれません。 コピー時の参照共有でScalaがどれだけ優れているかわかりません 誰かコメントできますか?

ケースクラスを使用する場合、上記の遅延評価の答えは正しいです。

0


タイトルとURLをコピーしました