如何确保我不会通过更改参考文献来更改原文?

时间:2016-10-31 21:29:29

标签: scala

免责声明:我不确定我的问题解释得非常好。我很乐意提出澄清建议。

这样的事情
val a = DenseVector.ones[Double](2)
val b = a
b(1 to 1) := 2.0
a // return: breeze.linalg.DenseVector[Double] = DenseVector(1.0, 2.0)
Scala中的

对像我这样的数学家来说是一个问题,而这不是问题,例如在R

a = c(1,1)
b = a
b[1] = 2.0
b // return: [1] 1 2
a // return: [1] 1 1

我不知道如何调用上述现象,但我该如何避免呢?如果我理解正确,可以通过在所有类不可变集合中使用val来避免它,其中集合的不可变集合类型是,其中每个条目都是val而不是外行人var。当给函数一个对象时,这个非复制但引用问题也会发生,我不太确定会发生什么(副作用,但是当我返回它而不是新创建的对象时)。即使def myfct(val myparameter)也不能保证my参数的var没有被更改,所以我应该只提供val个参数。

所有这些听起来都很容易出错 - 我只是在等我做一些市长的错误。我很少想要传递对象的引用,而不是深层复制。单元测试真的是唯一的方法(即使那时我必须考虑可能发生的所有可能的错误)我可以测试我不会忘记制作深层副本(通过创建新对象显式或隐式)?

如何通过更改参考来确保我不会错误地更改原件?是使用val和不可变集合的唯一答案还是有另一种设计模式?例如。是否存在一种设计模式,即使输入是可变集合或具有可变成员的对象,我也可以将函数的输入参数设置为不可变的?

1 个答案:

答案 0 :(得分:1)

Scala允许可变对象,看起来breeze.linalg.DenseVector是一个可变对象。

但是,它也对不可变结构有很好的支持。有一个不可变的集合API,它包含所有内容的不可变版本:

scala> val a = Vector(1,1,1) // note the "scala.collection.immutable namespace"
a: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1)

scala> val b = a  // not a deep copy, but a shared ref to an immutable object
b: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1)

// mutating operations on immutable objects will return a modified
// copy, leaving the origin object unchanged
scala> b.updated(1, 2)  
res0: scala.collection.immutable.Vector[Int] = Vector(1, 2, 1)

scala> b
res1: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1)

scala> a
res2: scala.collection.immutable.Vector[Int] = Vector(1, 1, 1)

scala> val c = b.updated(1, 2)
c: scala.collection.immutable.Vector[Int] = Vector(1, 2, 1)
  

我很少想要传递对象的引用,而不是深层复制。

Scala和其他c系列语言不使用像“R”这样的深层副本。传递引用比使用防御副本更有效。如果对象是不可变的,那么只有在写入时才需要复制,而不是在读取时。