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).