プロセス辞書とは、Erlangの各プロセスが独自に持っている辞書のことです。 辞書というのはJavaでいうHashMap(HashTable)にあたり、キーとバリューを対応付ける表のようなものです。
後ほど実験を行ないますが、このプロセス辞書は自分のプロセス内でのみ有効だという点に注意が必要です。 したがって、プロセスAがプロセスBの辞書にアクセスを行なうということはできません。
プロセス辞書で使われる関数は、全てBIFのerlangモジュールに格納されていますので、 モジュール名を宣言せずに関数を使用することが可能です。
それでは、使われる関数を見ていきましょう。
関数 | 役割 |
---|---|
put(Key,Value) | KeyとValueを新しく対応付ける。前に設定されていた値を返す |
get(Key) | Keyで対応付けられているValueを返す。Keyが存在しなければundefinedを返す。 |
get() | KeyとValueをタプルでまとめ、全ての組み合わせをリストで返す。 |
get_keys(Value) | 値Valueと対応付けられている全てのKeyをリストで返す。なければ空のリストを返す。 |
erase(Key) | Keyに組み合わされているValueを返す。そしてそのあとその組み合わせを削除する。 |
erase() | KeyとValueをタプルでまとめ、全ての組み合わせをリストで返す。そして全てを削除する。 |
それでは、実際にプロセス辞書を使ってみましょう。
1> put(apple,200).
undefined
2> put(orange,150).
undefined
3> get(apple).
200
4> put(peach,200).
undefined
5> get_keys(200).
[peach,apple]
6> get_keys(150).
[orange]
7> get().
[{peach,200},{apple,200},{orange,150}]
8> erase(peach).
200
9> get(peach).
undefined
10> get().
[{apple,200},{orange,150}]
11> erase().
[{apple,200},{orange,150}]
12> get().
[]
重要なことは、同じKeyを重複して持つことができないということです。
Valueは同じ値があっても構いませんが、辞書内にあるKeyは必ず重複していません。
すでにあるKeyと、Valueを対応付け用とすると、Valueが古い物から新しい物へ更新されます。
1> put(orange,150).
undefined
2> put(orange,200).
150
3> get(orange).
200
先ほどお伝えしたように、自分のプロセス内のプロセス辞書にのみアクセスすることが可能です。。 少し実験をしてみて確認をしたいと思います。
-module(proc_dic).
-export([test/0, call/2]).
call(Pid, Message) ->
Pid ! {self(), Message},
receive
{Pid, Response} ->
Response
end.
test() ->
put(apple,200),
put(orange,150),
loop().
loop() ->
receive
{From, {get,Key}} ->
From ! {self(), get(Key)},
loop();
{From, {put, Key, Value}} ->
From ! {self(), put(Key, Value)},
loop()
end.
call/2は以前やったものとほとんど同じです。これはプロセスへの処理の依頼をします。
ただ、receive分の中にあるパターンマッチに、送信先のPidが含まれていますね。これは選択受信を行なうためのものです。 つまり、送信先プロセス以外からのメッセージは処理されないで無視されます。
test/0は辞書に値を登録した後にループに入ります。今回は別のプロセスで使われ、サーバとなります。
実行してみます。
新しくプロセスを作成し、その中で辞書にkeyとvalueを登録。
1> Pid = spawn(proc_dic,test,[]).
<0.33.0>
辞書から値を得ようとしても、別のプロセス内の辞書にはアクセスできない。
2> get(apple).
undefined
メッセージを使って、相手先のプロセスに辞書の参照や、新たな項目の作成をしている。
3> proc_dic:call(Pid,{get,apple}).
200
4> proc_dic:call(Pid,{put,banana,50}).
undefined
5> proc_dic:call(Pid,{get,banana}).
50
あくまでも、プロセス辞書はプロセス内でのみ共有できるということがわかりましたね。