2016-10-31 4 views
0

면책 조항 : 나는 나의 질문을 정말 잘 설명 할 수 있을지 확신하지 못한다. 나는 해명을위한 제안에 만족합니다. 이 예를 들어, 문제가되지 않습니다 동안참조를 변경하여 원본을 변경하지 않는 방법은 무엇입니까?

스칼라에서
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) 

같은


것들, 나 같은 수학들에 대한 문제의 친절 in R

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

위의 현상이 어떻게 불리는 지 모르지만 어떻게 피할 수 있습니까? 만약 내가 올바르게 이해한다면 모든 클래스에서 val을 사용하여 피할 수 있습니다. 불변의 콜렉션. 컬렉션의 불변 콜렉션 정렬이 있습니다. 각 엔트리는 var 대신에 val입니다. 이 not-copy-but-reference-issue는 함수에 객체를 줄 때 일어나는 일이며, 어떤 일이 일어날 지 잘 모르겠습니다 (부작용뿐 아니라 새로 만든 객체 대신 반환 할 때도 마찬가지입니다). def myfct(val myparameter)조차도 var 초의 myparameter가 변경되지 않는다는 것을 보장하지 않으므로 val만을 배타적으로 제공해야합니다.

이 모든 것이 너무 오류가 발생하기 쉬운 것 같습니다. 저는 시장의 실수를 저지르는 것을 기다리고 있습니다. 매우 드물게 나는 객체에 대한 레퍼런스를 전달하기를 원합니다. 유닛 테스트가 실제로 유일한 방법입니까? 그리고 심지어 발생할 수있는 모든 가능한 오류를 생각해야합니다. 새로운 개체를 만들어 명시 적으로 또는 암시 적으로 전체 복사본을 만드는 것을 잊지 않도록 테스트 할 수 있습니까?

참조를 변경하여 원본을 변경하는 실수를하지 않도록하려면 어떻게해야합니까? val 및 불변의 컬렉션을 사용하는 유일한 대답입니까 아니면 다른 디자인 패턴입니까? 예 : 입력이 변경 가능한 컬렉션이거나 변경 가능한 멤버가있는 객체 인 경우에도 불변 인 함수에 대한 입력 매개 변수를 만들 수있는 디자인 패턴이 있습니까?

+1

스칼라는 원하는대로 변경할 수 없습니다. 변경되지 않는 구조체를 사용하는 경우 ... 잘 ... 불변합니다. 당신이 가변적 인 것들을 사용한다면, 그것들은 변하지 않습니다. 나는 당신의 문제가 무엇인지 이해하지 못합니다. 돌연변이가 될만한 물건이 마음에 들지 않으면 그것을 사용하지 마십시오. 깊은 복사본을 만들지 마십시오 (비효율적이고 느립니다), 때마다 변경할 수없는 구조체를 사용하십시오. – Dima

+0

'b [1] = 2.0'은 불변 객체에 대한 연산처럼 보이지 않으므로 변경되지 않을 수도 있습니다. 변경할 수없는 객체를 사용할 때 참조 문제는 단순히 존재하지 않습니다. 그렇지 않으면 가장 최근의 OOP 언어인데 참조 사본 만 알고 있습니다. –

+0

@Dima : 나는 내 질문을 개선하려고 노력했다. – Make42

답변

1

스칼라는 변경 가능한 개체를 허용하며 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) 

만 매우 드물게 내가 정말 객체를 참조하지 깊은 사본을 전달해야합니다.

스칼라 및 다른 c-family 언어는 "R"과 같이 깊은 복사본을 사용하지 않습니다. 방어 복사본을 항상 가져가는 것보다 참조를 전달하는 것이 더 효율적입니다. 오브젝트가 불변 인 경우, 카피는 카피에 필요 합니다만, 카피에는 필요 없습니다.

관련 문제