Kernael
Kernael

Reputation: 3280

Elixir - Randomized numbers in Agent

I'm trying to implement an Agent that behaves as a dice :

defmodule Dice do
  @on_load :seed_generator

  def start_link(opts \\ []) do
    Agent.start_link(fn -> [] end, name: __MODULE__)
  end

  def roll(n, val) do
    Agent.cast(__MODULE__, fn(_) ->
      Stream.repeatedly(fn -> :random.uniform(val) end)
      |> Enum.take(n)
    end)
  end

  def seed_generator do
    :random.seed(:erlang.now)
    :ok
  end
end

However, the generated numbers are the same, every time I restart iex. What am I doing wrong ? Is the seed not working because the :random.uniform call is inside the Agent ? Or something related with the Stream maybe.

Upvotes: 12

Views: 810

Answers (1)

Paweł Obrok
Paweł Obrok

Reputation: 23194

The seed_generator function is called in a different process than the one your Agent will be using. In fact that process doesn't even exist at the point this code is loaded. Try seeding the generator when starting the Agent:

defmodule Dice do
  def start_link(opts \\ []) do
    Agent.start_link(fn -> :random.seed(:erlang.now) end, name: __MODULE__)
  end

  def roll(n, val) do
    Agent.get(__MODULE__, fn(_) ->
      Stream.repeatedly(fn -> :random.uniform(val) end)
      |> Enum.take(n)
    end)
  end
end

Upvotes: 8

Related Questions