2011-12-09 16 views
5

저는 스칼라를 처음 사용합니다. 클로저가 메시지의 일부로 액터로 전달 될 때 scala가 동적 바인딩을 수행하는 방법을 이해하려고합니다.액터와 함께 사용할 때 스칼라 변수 바인딩

저는 Scala 2.9에서 Akka 1.2를 사용하고 있습니다.

제가 단순히 제 isAdult 파라미터를 적용하고 그 결과를 출력 (http://gleichmann.wordpress.com/2010/11/15/functional-scala-closures/에서 변형) 다음 코드 세그먼트 액터 측에서는

var minAge = 18 
val isAdult = (age: Int) => age >= minAge 

actor ! answer(19, isAdult) 
minAge = 20 
actor ! answer(19, isAdult) 

있다. 스칼라 이후 는 사용 동적 바인딩 그래서 스칼라 정적 변수를 바인딩 (18)를 복용 그것이 사실이다, 내가

true 
false 

을 기대하지만, 어떻게 든 결과가

false 
false 

인 것이다 (그래서 나는 들었다) 응답 메시지 모두에 대해 minAge 값으로 사용 하시겠습니까? 메시지에서 클로저를 사용하는 동안 동적 바인딩 동작을 유지할 수있는 방법이 있습니까?

감사합니다.

답변

9

폐쇄에 대한 귀하의 이해가 정확합니다. 동적 바인딩을 수행하고 있지만 동시성 문제는입니다. 클로저는 변경 가능한 데이터에 바인딩되어있어 클로저가 변경 가능합니다. 액터 모델은 행위자간에 엄격하게 불변의 데이터를 전달할 때만 동시성 문제를 해결합니다. 겉으로보기에 시간순으로 쓸 수도 있지만 배우 스케줄러는 이벤트의 순서를 변경합니다. 그리고 isAdult가 변경 가능하기 때문에 재정렬은 결과를 변경합니다.

actor ! answer(19, isAdult) // message put in actor queue 
minAge = 20 
actor ! answer(19, isAdult) // message put in actor queue 
// later... 
// actor handles answer(19, isAdult) 
// actor handles answer(19, isAdult) 
+0

고마워요! 이것은 의미가 있습니다. 그래서 isAdult는 느리게 평가되고 액터가 실제로 메시지를 처리 ​​할 때까지 변수가 바인딩되지 않습니다. minAge = 20을 실행하기 전에 첫 번째 쿼리의 응답을 기다렸다가 예상 한 결과를 얻는 것 같습니다. – royalflush

+2

맞습니다만 절대 그렇게해서는 안됩니다 ;-) 진실로, 배우들 사이에서 변경 가능한 상태를 공유하고 싶다면 배우를 사용하지 않을 것입니다. 불행히도 스칼라는 "가치에 의한"접근을 막을 수있는 방법을 제공하지 않기 때문에, 당신이 할 수있는 유일한 일은 직접 닫은 모든 것이 'val'이라는 것을 수동으로 확인하는 것입니다. –

+0

단일 기계의 경우 인수가 사실이라고 생각합니다. 그러나 원격 배우들과 함께, 왜 안되죠? 예를 들어 두 액터간에 분산 상태를 동기화하는 메시지를 보낼 수 있습니까? – royalflush

관련 문제