免责声明:我不确定我的问题解释得非常好。我很乐意提出澄清建议。
像
这样的事情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
和不可变集合的唯一答案还是有另一种设计模式?例如。是否存在一种设计模式,即使输入是可变集合或具有可变成员的对象,我也可以将函数的输入参数设置为不可变的?
答案 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”这样的深层副本。传递引用比使用防御副本更有效。如果对象是不可变的,那么只有在写入时才需要复制,而不是在读取时。