2012-03-22 14 views
5

another questionに、Javaの同時マルチマップについて尋ねました。並行マルチマップと同等の機能

ScalaまたはClojureプログラムで代わりに使用できる機能プログラミング(不変)パターンはありますか? Scalaのソリューションにはおそらくアクターとクロージャーが含まれています。​​、refまたはagentが良い方法かもしれません。両方の言語がJavaの相互運用性に「落ち込み」を許し、Javaソリューションを使用するだけなので、私は最初の質問に答えを出すことができますが、それは機能プログラミングのパラダイムには従いません。 Haskellのプログラマはどのようにこれを解決しますか?

+1

は、それはHaskellは変異を許可していない一般的な誤解です。します。キャッチされているのは、すべての突然変異が型に正式に記載されなければならないということです。したがって、突然変異操作を一緒に構成する典型的な方法は、モナドインターフェースである。 HaskellersはScalaとClojureと同じようにmutabilityに "後退"することができますが、ハスケルを除いて、あなたが不正行為をすることはできません。しかし、あなたが完全にあなたの関数に変異をカプセル化することができれば、それは純粋なインターフェースをさらすことができます。 –

答えて

7

標準のClojureマップとセットは不変(かつ永続的)です[1]ので、並行プログラムでも同様に動作します。要件に応じてref/agent/var/atomに格納したい場合があります。ref/agent/var/atomをこれまでどおりに更新することができます。

あなたは値がこのように、実際に参照文献であれば、より多くの可変マップを持つことができます。

{:a (ref #{1 2 3}) 
:b (ref #{4 5 6})} 

この場合は、あなたが実際にすでにのトランザクションにキーを(既存する値を追加することができますコース)。追加、

user=> (def mmap {:a (ref #{1 2 3}) :b (ref #{4 5 6})}) 
#'user/mmap 
user=> mmap 
{:a #<[email protected]: #{1 2 3}>, :b #<[email protected]: #{4 5 6}>} 
user=> (def mmap2 (assoc mmap :c (ref #{7 8 9}))) 
#'user/mmap2 
user=> mmap2 
{:C#<[email protected]: #{7 8 9}>, :a #<[email protected]: #{1 2 3}>, :b #<[email protected]: #{4 5 6}>} 
user=> mmap 
{:a #<[email protected]: #{1 2 3}>, :b #<[email protected]: #{4 5 6}>} 
user=> (dosync (alter (:a mmap2) conj 0)) 
#{0 1 2 3} 
user=> mmap 
{:a #<[email protected]: #{0 1 2 3}>, :b #<[email protected]: #{4 5 6}>} 
user=> mmap2 
{:C#<[email protected]: #{7 8 9}>, :a #<[email protected]: #{0 1 2 3}>, :b #<[email protected]: #{4 5 6}>} 

[1]それは次のとおりです。キーの追加や削除は、まだ元のマップと同じ引用文献を共有することになる、新しいマップを返し、ので、それらのいずれかに変更が他の人に表示されます/キーを削除/変更すると、元の値を変更せずに値が実際に新しいマップを返します。

3

機能的なデータ構造は、不変のデータ構造です。不変のデータ構造は、変更できないため、並行性に問題はありません。

+0

このデータ構造を管理するには、アクター(またはアクターのようなクラス)がスレッドセーフな方法ですか? – Ralph

+2

@Ralphはまったくありません。アクターは便利ですが、並行性の問題ではありません。 Daniel sayaのように、あなたは不変構造の管理を一切必要としません。問題は、あなたが変更可能性を必要とするかどうか、もしあれば、どのように変更するかが決まります。詳細はこちらをご覧ください。 – Submonoid

関連する問題