2

我是 Scala 的新手,但我是一位经验丰富的程序员,试图摆脱旧习惯并采用函数式风格。我正在设计的一个简单程序涉及问题/答案对象,并保留了一些关于成功的基本事实。仅使用不可变对象就足够简单了——但我的部分目标是链接相关的事实,因此程序可能会不时地询问它们彼此相邻。(例如:“Knight Rider Car 是什么?”、“什么电视节目以 Impala 为主角?)

在 Java 中,我可能刚刚链接了如下所示的关联对象,但是不可变的法律阻止了这种情况(我不能链接 A-> B 并实例化 B -> A,除非我一次性完成?)

而且我必须承认,这可能是一件好事——也许函数式风格就是为了防止这种循环引用而设计的。但我不知道如何纠正这个问题。一旦提出问题,我的设计就会失败 - 因为这会返回一个具有“正确,询问”新值的副本对象,因此对象链接似乎又是一个陷阱。我最好的猜测是在辅助对象中构建关系集,仅基于 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)

  } 
4

2 回答 2

2

请参阅此问题以了解如何不可变地执行此操作:scala: how to model a basic parent-child relationship

提示:不要在案例类中执行此操作,除非您重写toString为不包含项目列表(如果存在循环引用,您将溢出堆栈,因为该项目的 toString 包括列表中所有其他项目的 toString )。

private var一旦您引用了列表项,您可以通过创建 List a 并从创建所有项的伴随对象中的工厂方法更新所有实例来为自己省去很多麻烦。由于没有公共设置器,它仍然是有效的不可变的。

一种类似且理论上可能更合理的方法是使列表 aStream从伴随对象中的映射中获取其值。在创建项目时地图必须是可变的,但至少项目现在是完全不可变的。

于 2012-06-06T00:09:42.143 回答
2

真正的答案是不要那样做。创建一个指向两者的“关系”对象。

现在您可能想知道如何从指向“Relation”的对象到“Relation”本身,然后是另一个对象,您可以通过使用 zippers 来做到这一点。不是直接去对象“a”,而是得到树/图,并将拉链移动到“a”。从那里,您可以返回“关系”并转发到“b”,或者如果拉链知道横向移动,则可以直接从“a”到“b”。

不幸的是,在有用的拉链方面,Scala 远远落后于 Haskell。但是,如果您了解这个概念(我将留给您研究),您总是可以为您的数据结构创建一个。

还有另一个可能适用的答案。您可能有一个“镜头”,它是一个知道如何将其他对象分开和组合(修改)的对象。该类的基本设计必须允许它(使用可变性或惰性技巧),但镜头隐藏了操作本身的丑陋(除了提供许多其他漂亮的功能)。

最后,我想强调 Scala不是纯函数式的,这是有充分理由的:Odersky 认为在纯函数式语言之外还有其他价值,并希望您拥有这种能力。

于 2012-06-06T03:24:03.987 回答