2011-12-09 32 views
5

私はScalaをかなり新しくしています。 私は、クロージャがメッセージの一部としてActorに渡されたときに、scalaが動的バインディングを行う方法/方法を理解しようとしています。アクターと一緒に使用する場合のScala変数バインド

私はScala 2.9でAkka 1.2を使用しています。

Iは、(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) 

を有し、それは単に最初のパラメータにisAdultを適用し、結果を印刷します。 Scalaは(私が言われた)動的バインディング使用しているので 、私は

true 
false 

を期待しているだろうが、何とか結果は

false 
false 

だから、Scalaは静的変数を結合し、18を取っていることは事実です両方の応答メッセージの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

これは間違いありませんが、決してそれをしないように心がけてください;-)真剣に、あなたはそれらの間で変更可能な状態を共有したい場合、あなたは俳優を使用しません。残念ながら、Scalaは "価値のある"値を閉じる方法を提供していないので、あなたができる唯一のことは、あなたが閉じるすべてのものが 'val'であることを手動で保証することです。 –

+0

私は、引数が単一のマシンの場合に当てはまると思います。リモートアクターと一緒に、なぜそうではありませんか?たとえば、2つのアクターの間で分散状態を同期させるメッセージを送信できますか? – royalflush

関連する問題