带有案例类的双向参考
是否可以在案例类中实现双向树。这看起来应该很容易,但我被难住了,
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
}
}
Is it possible to implement a bi-directional tree in a case class. This seems like it should be easy, but I'm getting stumped
case class Node(name:String, parent:Option[Node], children:List[Node])
I want to add a child (and get a new root) -- something like
def addChild(n:String):Node = {
Node(name, parent, Node(n, Some(this), Nil)::children)
}
But that won't work because the "parent" in the child will no longer refer to the Node which lists the child as a child. Is this possible with immutable lists and case classes?
Based on answer given below
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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我最近在 Twitter 上向 @jamesiry 问了同样的问题:-)。
他的回答是:
I asked the same question to @jamesiry on Twitter recently :-).
His answer:
请注意:考虑案例类是否是表示树的好选择。
由于案例类是值类型,因此返回父级的唯一方法是返回父级的副本,包括完整子树的副本。然后,如果您枚举其子树,您将再次获得完整子树的副本。
如果您想在树中进行一些替换,例如替换更深层次上的节点,唯一的方法就是复制完整的树并丢弃旧的树。
这一切看起来有点笨拙,但例如 lift- json 使用 case 类来表示 JSON AST,因此这可能不是什么大问题。不确定 Scala 在复制时的参考共享方面有多好。也许有人可以发表评论?
如果您确实想使用案例类,那么上面带有惰性评估的答案是正确的。
Just a note: think if case classes are a good option for you to represent a tree.
Since case classes are value types, the only way to return parent is to return a copy of the parent, including a copy of the full subtree. Then if you for example enumerate its children, you will again get copies of the full subtrees.
If you want to do some replacements in the tree, e.g. replace a node on some deeper level, the only way again is to make a copy of the full tree and throw away the old tree.
This all seems a bit clumsy, but for example lift-json uses case classes to represent JSON ASTs, so it might not be that much of a problem. Not sure how good Scala is at reference sharing when copying. Maybe someone can comment?
If you do want to use case classes, the answer above with lazy evaluation is correct.