2015-05-25 20 views
12

sto cercando di implementare un agente che si comporta come un dado:Elixir - numeri randomizzati in Agente

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 

Tuttavia, i numeri generati sono gli stessi, ogni volta che riavvio IEX. Cosa sto sbagliando? Il seme non funziona perché la chiamata :random.uniform si trova all'interno dell'agente? O qualcosa in relazione con lo Stream forse.

risposta

8

La funzione seed_generator viene chiamata in un processo diverso da quello che verrà utilizzato da Agent. In realtà quel processo non esiste nemmeno nel momento in cui questo codice viene caricato. Prova semina il generatore quando si avvia il 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 
+0

sembra funzionare, ha fatto questo: 'Agent.start_link (fn ->: random.seed (: erlang.now); [] fine, il nome: __MODULE __)' mantenere una lista vuota come stato predefinito. Grazie. – Kernael

+0

Stai ignorando lo stato comunque nella funzione 'roll', quindi non penso che importi. Il tuo stato attuale è il dizionario del processo in cui viene mantenuto lo stato del generatore casuale. –

+2

Invece di erlang.now(), la funzione os.timestamp() potrebbe anche essere buona: http://www.erlang.org/doc/man/os.html#timestamp-0 Perché erlang.now() potrebbe portare alcuni problemi. – h4cc