てきとうなメモ

本の感想とか技術メモとか

process dictionary

erlangはプロセスごとにディクショナリを持っている.putで値をいれ,getで取得し,eraseで消す.

1> put(foo, {1, 2, 3}).
undefined
2> put(bar, "hoge").
undefined
3> get(foo).
{1,2,3}
4> get(bar).
"hoge"
5> get().
[{foo,{1,2,3}},{bar,"hoge"}]
6> put(bar, "fuga").
"hoge"
7> get(bar).
"fuga"
8> erase(foo).
{1,2,3}
9> get(foo).
undefined
10> erase().
[{bar,"fuga"}]
11> get().
[]

例えばrandomなどで利用されている.randomはseed()で種をセットする.

1> random:seed().
{3172,9814,20125}

その後,random:uniform()で乱数を取得できる

2> lists:map(fun(X) -> random:uniform() end, lists:seq(1,10)).  
[9.23009e-2,
 0.443585,
 0.723040,
 0.945816,
 0.501491,
 0.311327,
 0.597448,
 0.915656,
 0.666957,
 0.477121]
3> lists:map(fun(X) -> random:uniform(10) end, lists:seq(1,10)).
[6,2,3,7,2,6,3,5,5,1]

random:seed()で帰ってくる3つの整数値が乱数生成器の状態を表しているのだが,これは内部の状態を表しているので,引数に渡したくない.そのためprocess dictionaryを用いて実装されている.

ソースは以下のようになっている.

seed()はseed(A1,A2,A3)を呼び出し,状態をrandom_seedとして登録する.

seed(A1, A2, A3) ->
    put(random_seed, 
        {abs(A1) rem 30269, abs(A2) rem 30307, abs(A3) rem 30323}).

uniformを実行するときはrandom_seedを取得して乱数値を計算する

uniform() ->
    {A1, A2, A3} = case get(random_seed) of
                       undefined -> seed0();
                       Tuple -> Tuple
                   end,
    B1 = (A1*171) rem 30269,
    B2 = (A2*172) rem 30307,
    B3 = (A3*170) rem 30323,
    put(random_seed, {B1,B2,B3}),
    R = A1/30269 + A2/30307 + A3/30323,
    R - trunc(R).