【问题标题】:how to access complex data structures in Scala while preserving immutability?如何在保持不变性的同时访问 Scala 中的复杂数据结构?
【发布时间】:2012-07-08 19:24:22
【问题描述】:

呼叫专家 Scala 开发人员!假设您有一个表示可写数据存储的大对象。您对这种常见的类似 Java 的方法感到满意吗:

val complexModel = new ComplexModel()
complexModel.modify()
complexModel.access(...)

或者你更喜欢:

val newComplexModel = complexModel.withADifference
newComplexModel.access(...)

如果您愿意,并且您有一个客户访问该模型,那么该客户的进展如何 要知道指向 newComplexModel 而不是 complexModel?从用户的角度 你有一个可变的数据存储。您如何协调这种观点与 Scala 的强调 关于不变性?

这个怎么样:

var complexModel = new ComplexModel()
complexModel = complexModel.withADifference
complexModel.access(...)

这似乎有点像第一种方法,只是 withADifference 内部的代码似乎比 modify() 内部的代码要做更多的工作,因为它必须创建一个全新的复杂数据对象而不是修改现有的。 (是否遇到了不得不做更多工作来尝试保存的问题? 不变性?)另外,你现在有一个大范围的 var。

您将如何决定最佳策略?您选择的策略有例外吗?

【问题讨论】:

    标签: scala data-structures functional-programming immutability


    【解决方案1】:

    我认为实用的方法是让 Stream 包含所有不同版本的数据结构,而消费者只是试图从该流中提取下一个元素。

    但我认为在 Scala 中,这是一种绝对有效的方法,可以在一个中心位置进行可变引用并对其进行更改,同时您的整个数据结构保持不可变。

    当数据结构变得更加复杂时,您可能会对这个问题感兴趣:Cleaner way to update nested structures 询问(并得到回答)如何实际创建不可变数据结构的新更改版本,这并不简单。

    【讨论】:

    • 确实如此。这是更多信息。可变上下文应该使用 STM... 在 Akka 中查找代理。更新结构应该使用镜头和状态来保持功能,看看 Scalaz。这种流通常称为事件溯源。
    • 有没有我可以浏览的开源项目作为“让 Stream 包含所有不同版本的数据结构,而消费者只是试图从该流中提取下一个元素”的策略示例?
    【解决方案2】:

    仅通过 modify 这样的方法名称,很容易将您的 ComplexModel 识别为 mutator 对象,这意味着它会更改某些状态。这仅意味着这种对象与函数式编程无关,并且试图使其不可变只是因为知识有问题的人告诉您 Scala 中的所有内容都应该是不可变的,这只是一个错误。

    现在您可以修改您的 api 以便 ComplexModel 对不可变数据进行操作,顺便说一句,我认为您应该这样做,但您绝对不能尝试将这个 ComplexModel 转换为不可变本身。

    【讨论】:

      【解决方案3】:

      您问题的规范答案是使用Zipper,一个SO question about it

      我知道的 Scala 的唯一实现是 ScalaZ

      【讨论】:

      • 是的,谢谢,我想我正在寻找拉链或镜片之类的东西。可惜他们不在“普通”的 Scala 中。
      【解决方案4】:

      不变性只是一个有用的工具,而不是教条。会出现不变性的成本和不便超过其用处的情况。

      ComplexModel 的大小可能使得创建修改后的副本在内存和/或 CPU 方面足够昂贵,因此可变模型更实用。

      【讨论】:

      • 是的,但是有些人会抱怨说,如果您的数据结构不是不可变的,那么您就没有获得 Scala 的主要优势,而且您还不如仍然使用 Java。
      • 函数式编程并不是 Scala 相对于 Java 的唯一优势。对于一个非常复杂的模型,我很想将它包装在一个 actor 中——这通常不是任何事情的 Java 解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      • 2020-01-03
      • 1970-01-01
      相关资源
      最近更新 更多