Search code examples
randomelixiragent

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.


Solution

  • 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