読者です 読者をやめる 読者になる 読者になる

c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programmingに分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡

音樂はSoundCloud等バラバラの場所に公開中です。申し訳ないがlinkをたどるなどして探してください。

考察は現在は主に此のblogで公表中です。

programmingは、ひろくみせるものはGitHubで、個人的なものはBitBucketで開発中です。

c4se

ElixirにてListのランダムな要素を取得する

Rubyだと

xs.sample

である。JavaScriptだと

xs[Math.floor(Math.random() * xs.length)];

となる。Elixirでもこれに近いことを行ふ。Erlangのrandomモジュールを使ってみると

Enum.at(xs, :random.uniform(Enum.count xs) - 1)

となる。これでよささうに見える。しかし何回か試してみるとわかるが、randomの乱数列はシードが一定なのだ。手動でシードしてやらなければやらない。

:random.seed :os.timestamp
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)

:random.seed :os.timestamp
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)
IO.inspect Enum.at(xs, :random.uniform(Enum.count xs) - 1)

これでよささうに見える。だがこのシードはプロセスごとに独立してゐるのだ。つまりプロセスを作るたびにプロセスの中でシードしてやらねばならない。しかもこれだとミリ秒の精度だから、プロセスを高速に大量につくるErlang (Elixir) では、頻繁にシードがかぶってしまふ。困る。
そこでrandomの代はりにcryptoモジュールを使ってみる。

Enum.at xs, rem(:crypto.bytes_to_integer(:crypto.rand_bytes 1), Enum.count xs)

重さうだが以上の欠点はない。cryptoの値でrandomをシードしてやるのもよいとおもふ。