Scala 的不变性是不是意味着无法修改列表或无法修改列表及其内容?

Posted

技术标签:

【中文标题】Scala 的不变性是不是意味着无法修改列表或无法修改列表及其内容?【英文标题】:Does Scala's immutability mean the list can't be modified or the list and its contents can't be modified?Scala 的不变性是否意味着无法修改列表或无法修改列表及其内容? 【发布时间】:2022-01-01 11:03:40 【问题描述】:

我正在学习 Scala 和函数编程及其不变性概念。

如果我的代码对这样的对象列表进行操作:

class Devices(
  val devices_df: Dataset[Row],
)
  private lazy val _devices = _initialize_list_of_devices()

  def devices(): List[Device] = 
    _devices
  

  private[this] def _initialize_list_of_devices(): List[Device] = 
    val devices_list = ListBuffer[Device]()
    for (device <- devices_df.collect()) 
      devices_list += new Device(
        device.getAs[String]("DeviceName"),
      )
    
    devices_list.toList
  

然后我像这样初始化列表:

  val devices_list = new Devices(devices_df).devices()

然后,我像这样更新列表中的对象:

  for (device <- devices_list) 
    device.modify_instance_properties()
  

代码有效,我可以修改列表中的对象。

但是,当我尝试使用以下内容将另一个对象添加到列表中时:

devices_list += new Device("append another device")

不管是val devices_list还是var devices_list都会失败。

我只是想理智地检查一下我没有误解事情,并想确认这些是真的:

不变性并不意味着列表中的对象不能被修改 对象似乎可以正常更新其属性 不变性确实意味着无法更改列表 我应该无法将另一个对象添加到列表中或从列表中删除现有对象

感谢您的宝贵时间和帮助????

【问题讨论】:

【参考方案1】:

所以List 是一个不可变集合,这意味着它的内容不能改变。 List 的实例将始终包含相同的对象。

List 包含的对象可以或不是不可变的,如果这些对象可以修改其内容,那么您可以“修改”List;但实际上 List 从未改变,因为它仍然指向相同的 (mutable) 对象。

val 是一个不可变引用,当您执行 val foo = x 时,您是在说 foo 将始终指向 x 对象(同样,它可能是可变或不可变的).

PS:你所有的代码都可以简化为:

final class Devices(val devices_df: Dataset[Row],) 
  lazy val devices =
    devices_df
      .collect()
      .iterator
      .map(device => device.getAs[String]("DeviceName"))
      .toList

【讨论】:

感谢您撰写并发布示例代码。这真的很有帮助。我在这里对语义感到困惑:So List is an immutable collection, which means that its contents can not be changed. An instance of a List will always contain the same objects.“内容”可以表示列表本身或对象本身。 “相同的对象”可以表示具有相同属性的相同对象。 为了让它对我有意义,你同意这个措辞吗?:`所以“List”是一个不可变的集合,这意味着“List”本身不能改变。 “列表”的实例将始终引用相同的对象。”这种措辞仍然成立吗? @ZhaoLi 是的,这正是我所说的,记住 List 要么是 Nil 要么是 Cons(a: A, tail: List[A]) 所以基本上是一个包含一个对象和指向下一个的指针的单元格链单元格,直到找到空单元格;所以在这种情况下,List 是不可变的意味着您不能更改单元格,它们将始终是相同的单元格并指向相同的单元格。 谢谢。我不认为我理解 Cons 部分,但我想我现在还好。 @ZhaoLi ....toList ++ List(device1, device2) 或类似的东西

以上是关于Scala 的不变性是不是意味着无法修改列表或无法修改列表及其内容?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 JavaScript 中的不变性如此重要(或需要)?

scala的trait执行报错: 错误: 找不到或无法加载主类 cn.itcast.scala.`trait`

GIT:斯坦福大学提出应对复杂变换的不变性提升方法 ICLR 2022

了解 SSTable 不变性

如何使用 Scala 从 Spark 中的列表或数组创建行

检查两个链表是不是合并。如果有,在哪里?