Двунаправленная ссылка с тематическими классами - PullRequest
9 голосов
/ 16 сентября 2010

Возможно ли реализовать двунаправленное дерево в классе дел.Кажется, это должно быть легко, но я становлюсь тупым

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
  }
}

Ответы [ 2 ]

9 голосов
/ 17 сентября 2010

Недавно я задал тот же вопрос @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
}
0 голосов
/ 31 июля 2012

Просто примечание: подумайте, являются ли классы падежей хорошим вариантом для представления дерева.

Поскольку классы case являются типами значений, единственный способ вернуть parent - это вернуть копию родительского объекта, включая копию полного поддерева. Затем, если вы, например, перечислите его дочерние элементы, вы снова получите копии полных поддеревьев.

Если вы хотите сделать некоторые замены в дереве, например, замените узел на каком-нибудь более глубоком уровне, единственный способ снова - сделать копию полного дерева и выбросить старое дерево.

Все это кажется немного неуклюжим, но, например, lift-json использует классы case для представления AST JSON, так что это может быть не такой большой проблемой. Не уверен, насколько хорош Scala при обмене ссылками при копировании. Может быть, кто-то может прокомментировать?

Если вы хотите использовать case-классы, ответ выше с ленивой оценкой верен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...