我是Scala的新手,但他是一位经验丰富的程序员,他试图摆脱旧习惯并加入功能风格。我正在设计的一个简单程序涉及问题/答案对象,并保留一些关于成功的基本事实。仅使用不可变对象就足够了 - 但我的目标之一是链接相关事实,因此程序可能会偶尔询问它们。 (例如:“骑士骑士车是谁?”,“什么电视节目以黑斑羚为特色?”
在Java中我可能刚刚链接了相关的对象,就像我在下面写的那样,但是不可变的法则阻止了这一点(我无法链接A-> B并实例化B - > A除非我一次性完成它? )
我必须承认,这可能是一件好事 - 也许功能风格旨在阻止这种循环引用。但我不知道如何纠正这个问题。一旦提出问题,我的设计就会失败 - 因为这会返回一个复制对象,其值为“right,ask”,因此对象链接似乎又是一个陷阱。我最好的猜测是在辅助对象中构建关系集,仅基于Q / A数据,但我想避免使用单独的数据模式对象。
谢谢大家 - 俄亥俄州哥伦布市的蒂姆
case class FactItem (
q:String, a:String,
right: Double = 0.0,
asked: Double = 0.0,
linked: List[FactItem] = List[FactItem]()
) {
def rP = right / asked //right per
def subLink( l:List[FactItem] ) : FactItem = {
this.copy( linked = l-this)
}
答案 0 :(得分:2)
有关如何以不可变的方式执行此操作,请参阅此问题:scala: how to model a basic parent-child relation
提示:不要在案例类中执行此操作,除非您覆盖toString
以不包括项目列表(如果存在循环引用,您将溢出堆栈,因为此项目的toString包括列表中所有其他人的toString。
通过使List成为private var
并在引用列表项后,在创建所有项目的伴随对象中更新工厂方法中的所有实例,可以节省很多麻烦。没有公共制定者,它仍然是有效的不可改变的。
类似的,理论上更合理的方法是使列表成为Stream
,从伴侣对象的地图中获取其值。
答案 1 :(得分:2)
真正的答案是不要那样做。创建一个指向两者的“Relation”对象。
现在你可能想知道你是如何从一个指向“关系”的对象转变为“关系”本身然后是另一个对象,你是通过使用拉链来实现的。您可以获得树/图,而不是直接转到对象“a”,而将拉链移动到“a”。从那里,如果拉链知道横向移动,您可以返回“关系”并转发到“b”,或直接从“a”转到“b”。
不幸的是,当谈到有用的拉链时,Scala远远落后于Haskell。但是如果你理解了这个概念(我将让你去研究),你总是可以为你的数据结构创建一个。
还有另一个可能适用的答案。你可能有一个“镜头”,它是一个知道如何分开并整理(修改)其他物体的对象。该课程的基本设计必须允许它(具有可变性或懒惰技巧),但镜片隐藏了操作本身的丑陋(除了提供许多其他漂亮的功能)。
最后,我想强调的是,Scala完全没有 纯粹的功能:Odersky认为纯函数式语言之外的价值,并希望你有这种能力。